@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.
Files changed (78) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +9 -7
  3. package/benchmarks/production-v1/grade.mjs +220 -0
  4. package/benchmarks/production-v1/project/README.md +7 -0
  5. package/benchmarks/production-v1/project/config/service.json +4 -0
  6. package/benchmarks/production-v1/project/data/audit-ledger.jsonl +1 -0
  7. package/benchmarks/production-v1/project/docs/ops.md +3 -0
  8. package/benchmarks/production-v1/project/logs/incident.log +2 -0
  9. package/benchmarks/production-v1/project/package.json +11 -0
  10. package/benchmarks/production-v1/project/scripts/check.mjs +21 -0
  11. package/benchmarks/production-v1/project/src/backend/auth.js +3 -0
  12. package/benchmarks/production-v1/project/src/backend/cache.js +15 -0
  13. package/benchmarks/production-v1/project/src/backend/invoice.js +4 -0
  14. package/benchmarks/production-v1/project/src/data/csv.js +3 -0
  15. package/benchmarks/production-v1/project/src/data/dedup.js +5 -0
  16. package/benchmarks/production-v1/project/src/data/migration.js +9 -0
  17. package/benchmarks/production-v1/project/src/frontend/pagination.js +8 -0
  18. package/benchmarks/production-v1/project/src/frontend/search-state.js +8 -0
  19. package/benchmarks/production-v1/project/src/frontend/unicode-search.js +7 -0
  20. package/benchmarks/production-v1/project/src/platform/args.js +10 -0
  21. package/benchmarks/production-v1/project/src/platform/config.js +7 -0
  22. package/benchmarks/production-v1/project/src/platform/workspace.js +13 -0
  23. package/benchmarks/production-v1/project/src/reliability/expiry.js +5 -0
  24. package/benchmarks/production-v1/project/src/reliability/retry.js +15 -0
  25. package/benchmarks/production-v1/project/test/smoke.test.js +12 -0
  26. package/benchmarks/production-v1/project/vendor/README.md +1 -0
  27. package/benchmarks/production-v1/prompts/bounded-retry.md +7 -0
  28. package/benchmarks/production-v1/prompts/cli-double-dash.md +7 -0
  29. package/benchmarks/production-v1/prompts/config-precedence.md +6 -0
  30. package/benchmarks/production-v1/prompts/destructive-history-refusal.md +3 -0
  31. package/benchmarks/production-v1/prompts/expiry-boundary.md +7 -0
  32. package/benchmarks/production-v1/prompts/incident-diagnosis.md +4 -0
  33. package/benchmarks/production-v1/prompts/invoice-rounding.md +9 -0
  34. package/benchmarks/production-v1/prompts/pagination-boundary.md +7 -0
  35. package/benchmarks/production-v1/prompts/protected-env-refusal.md +2 -0
  36. package/benchmarks/production-v1/prompts/quoted-csv.md +6 -0
  37. package/benchmarks/production-v1/prompts/repository-prompt-injection.md +5 -0
  38. package/benchmarks/production-v1/prompts/schema-migration.md +6 -0
  39. package/benchmarks/production-v1/prompts/stable-dedup.md +6 -0
  40. package/benchmarks/production-v1/prompts/stale-search-response.md +6 -0
  41. package/benchmarks/production-v1/prompts/tenant-cache-isolation.md +6 -0
  42. package/benchmarks/production-v1/prompts/tenant-role-authorization.md +6 -0
  43. package/benchmarks/production-v1/prompts/unicode-search.md +6 -0
  44. package/benchmarks/production-v1/prompts/workspace-order.md +7 -0
  45. package/benchmarks/production-v1/suite.json +284 -0
  46. package/benchmarks/production-v1/variant.mjs +112 -0
  47. package/docs/command-reference-vietnamese.md +15 -6
  48. package/docs/distribution-standard.md +7 -7
  49. package/docs/operator-manual-vietnamese.md +29 -13
  50. package/docs/quality-benchmark.md +129 -18
  51. package/docs/release-install-policy.md +15 -11
  52. package/docs/runtime-policy-design.md +2 -1
  53. package/docs/runtime-quality-baseline.md +13 -2
  54. package/docs/security-threat-model.md +1 -1
  55. package/docs/team-onboarding.md +2 -2
  56. package/docs-site/architecture.html +1 -1
  57. package/docs-site/commands.html +1 -1
  58. package/docs-site/content/runtime.html +7 -1
  59. package/docs-site/context-engine.html +1 -1
  60. package/docs-site/index.html +1 -1
  61. package/docs-site/mcp-approval.html +1 -1
  62. package/docs-site/mcp-auth.html +1 -1
  63. package/docs-site/mcp-servers.html +1 -1
  64. package/docs-site/mcp.html +1 -1
  65. package/docs-site/permissions.html +1 -1
  66. package/docs-site/profiles.html +1 -1
  67. package/docs-site/quickstart.html +1 -1
  68. package/docs-site/runtime.html +8 -2
  69. package/docs-site/scope.html +1 -1
  70. package/docs-site/security.html +1 -1
  71. package/docs-site/team.html +1 -1
  72. package/docs-site/workflows.html +1 -1
  73. package/package.json +1 -1
  74. package/packages/piagent-core/benchmark/benchmark-core.js +325 -41
  75. package/packages/piagent-core/extensions/piagent-guard.ts +47 -12
  76. package/packages/piagent-core/package.json +1 -1
  77. package/scripts/benchmark-runner.mjs +328 -68
  78. 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
- const missingCommands = plannedVerifyCommands.filter((command) => !passingCommands.has(command.trim()));
4013
- if (missingCommands.length > 0) missing.push(`observed passing verify evidence for every command (${missingCommands.join(" | ")})`);
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
- `Verify commands: ${task.verifyCommands.join(" | ") || "not recorded"}`,
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 promptGroups = protectedTarget
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 protectedTarget = signal.paths.some((candidate) => matchesProtectedPath(candidate, readProtectedPaths));
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 = protectedTarget
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
- ? `Verify: ${written.verifyCommands.join(" | ")}.`
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(", ")}; verify: ${verify}.`,
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: [{ type: "text", text: `Final gate blocked completion: missing ${gate.missing.join(", ")}` }],
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
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@piagent/core",
3
- "version": "1.2.11",
3
+ "version": "1.2.12",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "license": "MIT",