@piagent/platform 1.6.0 → 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.
Files changed (213) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +17 -14
  3. package/README.vi.md +26 -1
  4. package/benchmarks/production-v1/spend-control.v1.json +27 -3
  5. package/benchmarks/production-v1/suite.json +5 -1
  6. package/catalog/capabilities.json +16 -16
  7. package/docs/authority-manifest.md +1 -1
  8. package/docs/auto-delegation-policy.md +38 -73
  9. package/docs/command-reference-vietnamese.md +23 -31
  10. package/docs/context-engine.md +5 -3
  11. package/docs/context-window-policy.md +37 -1
  12. package/docs/distribution-standard.md +7 -7
  13. package/docs/en/architecture.md +26 -13
  14. package/docs/languages.json +4 -4
  15. package/docs/operator-manual-vietnamese.md +21 -41
  16. package/docs/publishing-for-teams.md +5 -0
  17. package/docs/quality-benchmark.md +179 -23
  18. package/docs/release-install-policy.md +6 -6
  19. package/docs/runtime-harness-standard.md +3 -3
  20. package/docs/security-threat-model.md +1 -1
  21. package/docs/subagent-orchestration-capabilities.md +19 -51
  22. package/docs/subagents-and-multiagent.md +21 -47
  23. package/docs/task-implementation-contract.md +3 -3
  24. package/docs/task-lifecycle-vietnamese.md +1 -1
  25. package/docs/team-onboarding.md +2 -2
  26. package/docs/vi/architecture.md +26 -13
  27. package/docs-site/architecture.html +1 -1
  28. package/docs-site/benchmark.html +89 -95
  29. package/docs-site/commands.html +1 -1
  30. package/docs-site/content/benchmark.html +88 -94
  31. package/docs-site/content/en/benchmark.html +134 -90
  32. package/docs-site/content/en/index.html +19 -19
  33. package/docs-site/content/en/runtime.html +4 -4
  34. package/docs-site/content/en/whats-new.html +12 -1
  35. package/docs-site/content/en/workflows.html +2 -2
  36. package/docs-site/content/index.html +19 -19
  37. package/docs-site/content/runtime.html +4 -4
  38. package/docs-site/content/whats-new.html +12 -1
  39. package/docs-site/content/workflows.html +2 -2
  40. package/docs-site/context-engine.html +1 -1
  41. package/docs-site/en/architecture.html +1 -1
  42. package/docs-site/en/benchmark.html +135 -91
  43. package/docs-site/en/commands.html +1 -1
  44. package/docs-site/en/context-engine.html +1 -1
  45. package/docs-site/en/index.html +20 -20
  46. package/docs-site/en/mcp-approval.html +1 -1
  47. package/docs-site/en/mcp-auth.html +1 -1
  48. package/docs-site/en/mcp-servers.html +1 -1
  49. package/docs-site/en/mcp.html +1 -1
  50. package/docs-site/en/permissions.html +1 -1
  51. package/docs-site/en/profiles.html +1 -1
  52. package/docs-site/en/quickstart.html +1 -1
  53. package/docs-site/en/runtime.html +5 -5
  54. package/docs-site/en/scope.html +1 -1
  55. package/docs-site/en/security.html +1 -1
  56. package/docs-site/en/team.html +1 -1
  57. package/docs-site/en/whats-new.html +13 -2
  58. package/docs-site/en/workflows.html +3 -3
  59. package/docs-site/index.html +20 -20
  60. package/docs-site/mcp-approval.html +1 -1
  61. package/docs-site/mcp-auth.html +1 -1
  62. package/docs-site/mcp-servers.html +1 -1
  63. package/docs-site/mcp.html +1 -1
  64. package/docs-site/permissions.html +1 -1
  65. package/docs-site/profiles.html +1 -1
  66. package/docs-site/quickstart.html +1 -1
  67. package/docs-site/runtime.html +5 -5
  68. package/docs-site/scope.html +1 -1
  69. package/docs-site/security.html +1 -1
  70. package/docs-site/team.html +1 -1
  71. package/docs-site/whats-new.html +13 -2
  72. package/docs-site/workflows.html +3 -3
  73. package/evals/fixtures/benchmark-assurance-evidence.invalid.json +1 -1
  74. package/evals/fixtures/benchmark-assurance-evidence.valid.json +1 -1
  75. package/evals/fixtures/codex-relative-efficiency-v1.invalid.json +4 -0
  76. package/evals/fixtures/codex-relative-efficiency-v1.valid.json +94 -0
  77. package/evals/fixtures/helper-request.invalid.json +1 -1
  78. package/evals/fixtures/helper-request.valid.json +1 -1
  79. package/evals/fixtures/piagent-webui/subagent-tree-v1.valid.json +7 -0
  80. package/evals/fixtures/task-authority-snapshot.valid.json +4 -4
  81. package/evals/fs4-readiness-matrix.v1.json +2 -2
  82. package/evals/fs5-causal-arm.v1.json +2 -2
  83. package/evals/fs5-pilot-protocol.v1.json +3 -3
  84. package/evals/fs5-pilot-protocol.v2.json +8 -8
  85. package/evals/fs5-pilot-protocol.v3.json +8 -8
  86. package/evals/fs5-pilot-protocol.v4.json +6 -6
  87. package/evals/fs5-pilot-protocol.v5.json +7 -6
  88. package/evals/private-holdout-v1/public-exposure.v1.json +1 -1
  89. package/evals/runtime-conformance-v1/README.md +43 -0
  90. package/evals/runtime-conformance-v1/evaluate-paid-canary.mjs +198 -0
  91. package/evals/runtime-conformance-v1/lane.json +57 -0
  92. package/evals/runtime-conformance-v1/paid-canary.json +31 -0
  93. package/evals/runtime-conformance-v1/runner.mjs +456 -0
  94. package/package.json +1 -1
  95. package/packages/piagent-core/README.md +13 -4
  96. package/packages/piagent-core/benchmark/benchmark-codex-relative-efficiency.js +698 -0
  97. package/packages/piagent-core/benchmark/benchmark-core.js +4 -3
  98. package/packages/piagent-core/benchmark/benchmark-forensics.js +4 -2
  99. package/packages/piagent-core/benchmark/benchmark-preflight.js +3 -1
  100. package/packages/piagent-core/benchmark/benchmark-provider-free-evidence.js +345 -0
  101. package/packages/piagent-core/benchmark/benchmark-record-validation.js +74 -5
  102. package/packages/piagent-core/benchmark/benchmark-report.js +15 -1
  103. package/packages/piagent-core/benchmark/benchmark-runtime-causal.js +244 -0
  104. package/packages/piagent-core/benchmark/benchmark-stage-diagnostic.js +201 -4
  105. package/packages/piagent-core/benchmark/benchmark-suite.js +22 -1
  106. package/packages/piagent-core/benchmark/benchmark-summary-support.js +4 -0
  107. package/packages/piagent-core/benchmark/benchmark-usage.js +15 -4
  108. package/packages/piagent-core/capabilities/runtime-integrity.js +3 -0
  109. package/packages/piagent-core/extensions/acceptance-behavior-proof.js +806 -0
  110. package/packages/piagent-core/extensions/acceptance-receipt.js +89 -48
  111. package/packages/piagent-core/extensions/context-engine.js +1 -11
  112. package/packages/piagent-core/extensions/context-index-policy.js +4 -0
  113. package/packages/piagent-core/extensions/context-query-paths.js +57 -0
  114. package/packages/piagent-core/extensions/criterion-context-pack.js +16 -3
  115. package/packages/piagent-core/extensions/criterion-graph.js +4 -1
  116. package/packages/piagent-core/extensions/fallback-base-policy.ts +101 -0
  117. package/packages/piagent-core/extensions/guard-types.ts +4 -0
  118. package/packages/piagent-core/extensions/piagent-guard.ts +194 -226
  119. package/packages/piagent-core/extensions/task-lifecycle.js +32 -0
  120. package/packages/piagent-core/extensions/task-state.js +69 -8
  121. package/packages/piagent-core/extensions/verification-intelligence.js +49 -12
  122. package/packages/piagent-core/extensions/workspace-evidence-roots.js +52 -16
  123. package/packages/piagent-core/package.json +1 -1
  124. package/packages/piagent-core/policies/base-policy.json +42 -2
  125. package/packages/piagent-core/policy/authority-manifest.v1.json +3 -3
  126. package/packages/piagent-core/prompts/be-to-fe.md +2 -8
  127. package/packages/piagent-core/prompts/plan.md +1 -1
  128. package/packages/piagent-core/prompts/platform-improve.md +2 -6
  129. package/packages/piagent-core/prompts/review.md +2 -7
  130. package/packages/piagent-core/prompts/scout.md +1 -1
  131. package/packages/piagent-core/prompts/task.md +4 -3
  132. package/packages/piagent-core/runtime/hooks/completion-hook.ts +7 -6
  133. package/packages/piagent-core/runtime/hooks/input-hook.ts +6 -0
  134. package/packages/piagent-core/runtime/hooks/session-start-hook.ts +100 -1
  135. package/packages/piagent-core/runtime/hooks/tool-result-hook.ts +58 -72
  136. package/packages/piagent-core/runtime/hooks/tool-result-value-helpers.ts +66 -0
  137. package/packages/piagent-core/runtime/inspection/bounded-emission-guard.ts +286 -0
  138. package/packages/piagent-core/runtime/inspection/runtime-event-store.ts +37 -7
  139. package/packages/piagent-core/runtime/inspection/task-subagent-tree.ts +27 -4
  140. package/packages/piagent-core/runtime/inspection/tool-failure-classification.ts +20 -3
  141. package/packages/piagent-core/runtime/inspection/webui-snapshot.ts +47 -11
  142. package/packages/piagent-core/runtime/orchestration/helper-lifecycle.ts +16 -12
  143. package/packages/piagent-core/runtime/orchestration/minimal-delegation-policy.ts +71 -0
  144. package/packages/piagent-core/runtime/orchestration/owned-work-budget.ts +28 -20
  145. package/packages/piagent-core/runtime/orchestration/role-policy.ts +27 -9
  146. package/packages/piagent-core/runtime/orchestration/subagent-tool-policy.ts +329 -0
  147. package/packages/piagent-core/runtime/policy/block-remedy.ts +0 -4
  148. package/packages/piagent-core/runtime/product/efficiency-metrics.ts +3 -0
  149. package/packages/piagent-core/runtime/quality/edit-freshness-guard.ts +102 -0
  150. package/packages/piagent-core/runtime/quality/exact-output-contract.ts +20 -10
  151. package/packages/piagent-core/runtime/quality/performance-assurance.ts +3 -3
  152. package/packages/piagent-core/runtime/recovery/continuation-budget.ts +1 -1
  153. package/packages/piagent-core/runtime/recovery/handoff-projection.ts +4 -1
  154. package/packages/piagent-core/runtime/recovery/pristine-task-policy-refresh.ts +91 -0
  155. package/packages/piagent-core/runtime/recovery/recovery-policy.ts +7 -4
  156. package/packages/piagent-core/runtime/recovery/resume-state.ts +112 -14
  157. package/packages/piagent-core/runtime/recovery/semantic-repair-handshake.ts +7 -13
  158. package/packages/piagent-core/runtime/recovery/task-evidence-coverage-refresh.ts +217 -0
  159. package/packages/piagent-core/runtime/registration/context-commands.ts +16 -2
  160. package/packages/piagent-core/runtime/registration/knowledge-tools.ts +9 -5
  161. package/packages/piagent-core/runtime/registration/operator-request-intake.ts +49 -0
  162. package/packages/piagent-core/runtime/registration/policy-tools.ts +4 -4
  163. package/packages/piagent-core/runtime/registration/session-commands.ts +1 -1
  164. package/packages/piagent-core/runtime/registration/task-completion-tools.ts +12 -9
  165. package/packages/piagent-core/runtime/registration/task-evidence-tools.ts +21 -12
  166. package/packages/piagent-core/runtime/registration/task-start-guidance.ts +19 -13
  167. package/packages/piagent-core/runtime/registration/task-start-manifest.ts +54 -0
  168. package/packages/piagent-core/runtime/registration/task-start-tool.ts +57 -57
  169. package/packages/piagent-core/runtime/runtime-limits.ts +16 -2
  170. package/packages/piagent-core/runtime/session/adaptive-context-analysis.ts +461 -0
  171. package/packages/piagent-core/runtime/session/adaptive-context-governor.ts +464 -0
  172. package/packages/piagent-core/runtime/session/adaptive-context-ledger.ts +265 -0
  173. package/packages/piagent-core/runtime/session/message-signals.ts +7 -3
  174. package/packages/piagent-core/runtime/session/operator-request-carry.ts +44 -0
  175. package/packages/piagent-core/runtime/session/runtime-state.ts +11 -7
  176. package/packages/piagent-core/runtime/session/source-checkout-read-grants.ts +35 -0
  177. package/packages/piagent-core/runtime/session/system-prompt.ts +76 -14
  178. package/packages/piagent-core/runtime/session/task-contract-presentation.ts +39 -0
  179. package/packages/piagent-core/runtime/tools/phase-tools.ts +8 -8
  180. package/packages/piagent-core/runtime/tools/tool-groups.ts +12 -2
  181. package/packages/piagent-core/runtime/verification/exact-verifier-reuse.ts +101 -0
  182. package/packages/piagent-core/runtime/workflows/runtime-intake-compaction.ts +164 -0
  183. package/packages/piagent-core/runtime/workflows/task-intake.ts +167 -39
  184. package/packages/piagent-core/subagents/piagent-oracle.md +5 -3
  185. package/packages/piagent-core/subagents/piagent-planner.md +6 -4
  186. package/packages/piagent-core/subagents/piagent-reviewer.md +5 -3
  187. package/packages/piagent-core/subagents/piagent-scout.md +4 -2
  188. package/packages/piagent-core/subagents/piagent-worker.md +6 -4
  189. package/packages/piagent-webui/dist/client/assets/{MarkdownMessage-CxeZqTte.js → MarkdownMessage-B4XehTCU.js} +1 -1
  190. package/packages/piagent-webui/dist/client/assets/{index-DynIMe8I.js → index-CgOEyRPG.js} +4 -4
  191. package/packages/piagent-webui/dist/client/index.html +1 -1
  192. package/packages/piagent-webui/extension/piagent-webui.ts +3 -1
  193. package/packages/piagent-webui/extension/same-session-bridge.ts +1 -1
  194. package/packages/piagent-webui/extension/session-stream-adapter.ts +33 -10
  195. package/packages/piagent-webui/gateway/gateway-session-stream.ts +37 -21
  196. package/packages/piagent-webui/gateway/session-operation-lifecycle.ts +237 -0
  197. package/packages/piagent-webui/gateway/session-operation-retry-control.ts +38 -0
  198. package/packages/piagent-webui/gateway/session-operation-watchdog.ts +9 -2
  199. package/packages/piagent-webui/gateway/session-runtime-supervisor.ts +8 -7
  200. package/packages/piagent-webui/ownership/session-lease-store.ts +5 -2
  201. package/packages/piagent-webui/server/core-inspection-provider.ts +2 -1
  202. package/packages/piagent-webui/server/transcript-projection.ts +91 -5
  203. package/schemas/codex-relative-efficiency-v1.schema.json +155 -0
  204. package/schemas/piagent-webui/runtime-event-v2.schema.json +15 -5
  205. package/schemas/piagent-webui/subagent-tree-v1.schema.json +11 -1
  206. package/schemas/project-profile.schema.json +1 -1
  207. package/schemas/task-contract.schema.json +15 -0
  208. package/scripts/benchmark-runner-core.mjs +14 -6
  209. package/scripts/benchmark-runner-finalization.mjs +4 -0
  210. package/scripts/configure-subagents.sh +42 -34
  211. package/scripts/helper-evaluation.mjs +1 -1
  212. package/scripts/team-doctor.sh +1 -1
  213. package/scripts/verify-local.sh +5 -0
@@ -1,18 +1,14 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- import { exactFinalOutputGuidance } from "../quality/exact-output-contract.ts";
3
- import { taskPerformanceAssurance } from "../quality/performance-assurance.ts";
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { exactFinalOutputGuidance } from "../quality/exact-output-contract.ts"; import { taskPerformanceAssurance } from "../quality/performance-assurance.ts";
4
2
  import { automaticTaskSummary, boundedRuntimeIntakeMessage } from "../workflows/task-intake.ts";
5
3
  import { WORKING_TREE_DIGEST_ALGORITHM } from "../../extensions/working-tree-digest.js";
4
+ import { TASK_ACCEPTANCE_CRITERIA_MAX, TASK_ACCEPTANCE_CRITERION_MAX_CHARS, TASK_EXPECTED_OUTPUT_MAX_CHARS, TASK_SUMMARY_MAX_CHARS, operatorRequestDigest } from "../../extensions/task-state.js";
6
5
  import { createEnvironmentBoundTaskAuthority } from "../policy/task-authority-runtime.ts";
7
6
  import { authorityReplacementState } from "../policy/authority-resume-policy.ts";
8
7
  import { compileCriterionGraph, criterionGraphContextSelection, criterionGraphContextSelectionDetails, criterionGraphGuidance, criterionGraphMode } from "../../extensions/criterion-graph.js";
9
8
  import { captureTaskStartBaseline } from "../inspection/task-baseline-start-capture.ts";
10
- import { sameStringRecord, satisfiesAuthorityReplacement } from "./task-start-retry-helpers.ts";
11
- import {
12
- automaticTaskExecutionGuidance, EXACT_VERIFIER_EXECUTION_GUIDANCE, RUNTIME_SOURCE_REUSE_GUIDANCE,
13
- taskCriticalProofSection
14
- } from "./task-start-guidance.ts";
15
- type ExtensionContext = any; type TaskContract = any; type TaskStartParameters = any;
9
+ import { sameStringRecord, satisfiesAuthorityReplacement } from "./task-start-retry-helpers.ts"; import { automaticTaskExecutionGuidance, EXACT_VERIFIER_EXECUTION_GUIDANCE, RUNTIME_SOURCE_REUSE_GUIDANCE, taskCriticalProofSection } from "./task-start-guidance.ts";
10
+ import { resolveTaskStartRepositoryManifestProvider } from "./task-start-manifest.ts"; import { boundedOperatorRequest, latestOperatorRequest } from "./operator-request-intake.ts";
11
+ type ExtensionContext = any; type TaskContract = any; type TaskStartParameters = Record<string, any> & { operatorRequest?: string }; function taskReferenceDetails(task: TaskContract, reasonCode: string): Record<string, unknown> { const scope = Array.isArray(task.scope) ? task.scope.slice(0, 50) : []; return { reasonCode, taskId: task.taskId, taskRunId: task.taskRunId, outcome: task.trace?.outcome, attempt: task.attempt, ...(reasonCode === "task-already-active" ? { scope, scopeTruncated: scope.length < task.scope.length } : {}) }; }
16
12
  export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any>): any {
17
13
  const {
18
14
  DEFAULT_MAX_TASK_ATTEMPTS, ORCHESTRATION_ROLES, REVIEW_LENSES, StringEnum, Type,
@@ -22,10 +18,11 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
22
18
  currentSessionName, defaultWorkPlan, effectiveProtectedPaths, hasGitEvidenceRoot, hasOperatorSessionName,
23
19
  isAcceptanceTestPath, loadProfileFromContext, matchesProtectedPath, normalizeReviewLenses, normalizeWorkPlanSteps, nowIso, policy,
24
20
  priorTaskAttempts, recordTaskStartCheckpoint, redactText, redactTextArray, registerRuntimeTool,
25
- repositoryFileManifest, repositoryFileManifestDetails, resolveOrchestrationPolicy, resolveTaskScopePatterns, runtimeLifecycleMode, runtimeState, safeTaskId, selectVerificationPlan,
21
+ repositoryFileManifest, resolveOrchestrationPolicy, resolveTaskScopePatterns, runtimeLifecycleMode, runtimeState, safeTaskId, selectVerificationPlan,
26
22
  summarizeAttempt, telemetry, validTaskScopePattern, validateNewWorkPlan, verifierCommandInstructions, workingTreeEvidenceDigest, workingTreeSnapshot, workingTreeSnapshotHasUnavailableEvidence,
27
23
  writeTask
28
24
  } = deps;
25
+ const repositoryManifestProvider = resolveTaskStartRepositoryManifestProvider(deps);
29
26
  const taskStartTool = {
30
27
  name: "piagent_task_start",
31
28
  label: "Piagent Task Start",
@@ -36,24 +33,24 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
36
33
  "Use source-change for project verifier execution or edits. For an assessment, report, or plan with no source changes, set mutationPolicy=forbidden; use read-only when no project verifier needs to execute.",
37
34
  "Do not call context, status, policy, evidence-recording, trace, or gate tools first; runtime hooks provide those checks automatically.",
38
35
  "Use tiny for a bounded low-risk change, normal for ordinary multi-file work, and high-risk for security, data, release, migration, or external-impact work.",
39
- "Every scope entry must be a project-relative path or glob such as src/file.ts, src/**, or test/**; never put prose in scope.",
36
+ "Every scope entry is an initial retrieval/review focus and must be a project-relative path or glob such as src/file.ts, src/**, or test/**; it is not a source-mutation boundary.",
40
37
  "Leave workPlan unset for ordinary tiny/normal tasks so runtime automation stays active; pass a custom workPlan only when the operator explicitly requests custom subagent or checkpoint orchestration.",
41
38
  "Tiny tasks use automatic lifecycle evidence; normal tasks retain one explicit review step; high-risk/custom plans keep manual checkpoints."
42
39
  ],
43
40
  parameters: Type.Object({
44
41
  taskId: Type.Optional(Type.String({ minLength: 1 })),
45
- summary: Type.String({ minLength: 10 }),
42
+ summary: Type.String({ minLength: 10, maxLength: TASK_SUMMARY_MAX_CHARS }),
46
43
  riskLane: StringEnum(["tiny", "normal", "high-risk"] as const),
47
44
  changeMode: Type.Optional(StringEnum(["source-change", "read-only"] as const, {
48
45
  description: "Use source-change for project verifier execution or edits; use read-only for bounded inspection."
49
46
  })),
50
47
  mutationPolicy: Type.Optional(StringEnum(["required", "forbidden"] as const, { description: "Required demands a final diff; forbidden allows exact verification, rejects source mutation, and requires a zero task delta." })),
51
48
  maxAttempts: Type.Optional(Type.Number({ minimum: 1, maximum: 10 })),
52
- expectedOutput: Type.String({ minLength: 10 }),
53
- acceptanceCriteria: Type.Array(Type.String({ minLength: 1 }), { minItems: 1, maxItems: 12 }),
49
+ expectedOutput: Type.String({ minLength: 10, maxLength: TASK_EXPECTED_OUTPUT_MAX_CHARS }),
50
+ acceptanceCriteria: Type.Array(Type.String({ minLength: 1, maxLength: TASK_ACCEPTANCE_CRITERION_MAX_CHARS }), { minItems: 1, maxItems: TASK_ACCEPTANCE_CRITERIA_MAX }),
54
51
  scope: Type.Array(Type.String({
55
52
  minLength: 1,
56
- description: "Project-relative path or glob only (for example src/file.ts, src/**, or test/**); do not use prose."
53
+ description: "Advisory retrieval/review focus as a project-relative path or glob (for example src/file.ts, src/**, or test/**); source changes may follow repository evidence beyond it."
57
54
  }), { minItems: 1, maxItems: 2000 }),
58
55
  outOfScope: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
59
56
  reviewLenses: Type.Optional(Type.Array(StringEnum(REVIEW_LENSES))),
@@ -74,12 +71,13 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
74
71
  _onUpdate: ((update: unknown) => void) | undefined,
75
72
  ctx: ExtensionContext
76
73
  ) {
77
- const profile = loadProfileFromContext(ctx);
78
- const createdAt = nowIso();
79
- const safeSummary = redactText(params.summary);
74
+ const profile = loadProfileFromContext(ctx), createdAt = nowIso();
75
+ const operatorRequest = typeof params.operatorRequest === "string"
76
+ ? params.operatorRequest
77
+ : latestOperatorRequest(ctx);
78
+ const safeSummary = redactText(params.summary), safeOperatorRequest = boundedOperatorRequest(operatorRequest, redactText);
80
79
  const taskId = safeTaskId(redactText(params.taskId ?? params.summary));
81
- const sessionId = ctx.sessionManager.getSessionId();
82
- const sessionName = currentSessionName(ctx);
80
+ const sessionId = ctx.sessionManager.getSessionId(), sessionName = currentSessionName(ctx);
83
81
  const active = activeSessionTask(ctx.cwd, sessionId) as TaskContract | undefined;
84
82
  if (active && active.trace.outcome !== "pending" && runtimeState.taskIdentity(ctx)?.taskRunId === active.taskRunId) {
85
83
  runtimeState.clearTaskBoundary(ctx, active.taskRunId);
@@ -135,12 +133,12 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
135
133
  }
136
134
  return {
137
135
  content: [{ type: "text", text: `Task already active in this session: ${active.taskId} (${active.taskRunId}). Reusing it instead of overwriting state.` }],
138
- details: compactTaskDetails(active)
136
+ details: taskReferenceDetails(active, "task-already-active")
139
137
  };
140
138
  }
141
139
  return {
142
140
  content: [{ type: "text", text: `Session already has pending task ${active.taskId} (${active.taskRunId}). Complete or stop it before starting another task in this conversation.` }],
143
- details: active,
141
+ details: taskReferenceDetails(active, "session-task-already-pending"),
144
142
  isError: true
145
143
  };
146
144
  }
@@ -155,24 +153,15 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
155
153
  };
156
154
  }
157
155
  const scopeResolution = resolveTaskScopePatterns(params.scope, repositoryFileManifest(ctx.cwd));
158
- if (scopeResolution.ambiguous.length > 0) {
159
- const details = scopeResolution.ambiguous
160
- .map((item) => `${item.input}: ${item.candidates.join(", ")}`)
161
- .join("; ");
162
- return {
163
- content: [{ type: "text", text: `Task start refused: scope is ambiguous (${details}). Use one exact project-relative candidate for each ambiguous entry.` }],
164
- details: scopeResolution,
165
- isError: true
166
- };
167
- }
168
- if (scopeResolution.unmatched.length > 0) {
169
- return {
170
- content: [{ type: "text", text: `Task start refused: scope entries do not identify an existing repository path (${scopeResolution.unmatched.join(", ")}). Use an exact project-relative path for a new file, such as src/name.ts, instead of a basename or guessed top-level alias.` }],
171
- details: scopeResolution,
172
- isError: true
173
- };
174
- }
175
- const resolvedScope = scopeResolution.scope;
156
+ // Scope guides context selection and review; it is not filesystem
157
+ // authority. Keep unresolved focus entries instead of preventing work in
158
+ // a parent workspace where several child repositories share names such
159
+ // as src/, app/, tests/, or package.json.
160
+ const unresolvedFocus = [
161
+ ...scopeResolution.ambiguous.map((item) => item.input),
162
+ ...scopeResolution.unmatched
163
+ ];
164
+ const resolvedScope = [...new Set([...scopeResolution.scope, ...unresolvedFocus])];
176
165
  const priorAttempts = priorTaskAttempts(ctx.cwd, taskId) as TaskContract[];
177
166
  const authorityStates = new Map(priorAttempts.map((task) => [task.taskRunId, authorityReplacementState(ctx.cwd, task)]));
178
167
  const unsafeAuthorityState = [...authorityStates.entries()].find(([, state]) => !state.enforcementSafe);
@@ -189,7 +178,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
189
178
  if (pendingElsewhere) {
190
179
  return {
191
180
  content: [{ type: "text", text: `Task ${taskId} is already active in session ${pendingElsewhere.sessionName ?? pendingElsewhere.sessionId} (${pendingElsewhere.taskRunId}).` }],
192
- details: pendingElsewhere,
181
+ details: taskReferenceDetails(pendingElsewhere, "task-active-in-another-session"),
193
182
  isError: true
194
183
  };
195
184
  }
@@ -197,7 +186,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
197
186
  if (latestCompleted) {
198
187
  return {
199
188
  content: [{ type: "text", text: `Task ${taskId} already completed as ${latestCompleted.taskRunId}. Use a distinct taskId for new work instead of replacing its evidence.` }],
200
- details: latestCompleted,
189
+ details: taskReferenceDetails(latestCompleted, "task-already-completed"),
201
190
  isError: true
202
191
  };
203
192
  }
@@ -260,11 +249,11 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
260
249
  const workPlan = providedWorkPlan.length ? providedWorkPlan : defaultWorkPlan(safeSummary, defaultPlanLane, changeMode, mutationPolicy);
261
250
  const workPlanError = validateNewWorkPlan(workPlan);
262
251
  if (workPlanError) {
263
- return { content: [{ type: "text", text: `Task start refused: ${workPlanError}.` }], details: workPlan, isError: true };
252
+ return { content: [{ type: "text", text: `Task start refused: ${workPlanError}.` }], details: { reasonCode: "invalid-work-plan" }, isError: true };
264
253
  }
265
254
  const firstReady = workPlan.find((step) => (step.dependsOn ?? []).length === 0);
266
255
  if (!firstReady) {
267
- return { content: [{ type: "text", text: "Task start refused: work plan has no dependency-ready first step." }], details: workPlan, isError: true };
256
+ return { content: [{ type: "text", text: "Task start refused: work plan has no dependency-ready first step." }], details: { reasonCode: "work-plan-has-no-ready-step" }, isError: true };
268
257
  }
269
258
  firstReady.status = "in-progress";
270
259
  firstReady.updatedAt = createdAt;
@@ -287,12 +276,15 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
287
276
  expectedOutput: redactText(params.expectedOutput),
288
277
  acceptanceCriteria: redactTextArray(params.acceptanceCriteria),
289
278
  changeMode,
279
+ mutationPolicy,
280
+ outOfScope: redactTextArray(params.outOfScope),
281
+ protectedPaths: profile.protectedPaths ?? [],
290
282
  source: params.intakeMode === "runtime" ? "runtime" : "model",
291
283
  generatedAt: createdAt
292
284
  });
293
285
  const criterionGraph = compileCriterionGraph({ acceptanceCriteria: acceptance.acceptanceCriteria, scope: resolvedScope,
294
286
  verifyCommands: verifyPlan.commands, changeMode, mode: criterionGraphMode(), createdAt });
295
- const projectManifest = repositoryFileManifestDetails(ctx.cwd), projectFiles = projectManifest.files;
287
+ const projectManifest = repositoryManifestProvider.read(ctx.cwd), projectFiles = projectManifest.files;
296
288
  const maxManifestFiles = contextBudgetConfig(policy).maxManifestFiles;
297
289
  const plannedSelection = criterionGraphContextSelectionDetails(criterionGraph, projectFiles, [], maxManifestFiles, projectManifest.complete, resolvedScope);
298
290
  const plannedContext = plannedSelection.entries;
@@ -309,6 +301,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
309
301
  maxAttempts,
310
302
  previousAttempts: priorAttempts.filter((task) => task.trace.outcome !== "pending").slice(0, 10).reverse().map(summarizeAttempt),
311
303
  summary: safeSummary,
304
+ ...(safeOperatorRequest ? { operatorRequest: safeOperatorRequest, operatorRequestDigest: operatorRequestDigest(safeOperatorRequest) } : {}),
312
305
  riskLane: params.riskLane,
313
306
  intakeMode: params.intakeMode === "runtime" ? "runtime" : "model",
314
307
  expectedOutput: redactText(params.expectedOutput),
@@ -331,7 +324,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
331
324
  orchestration: {
332
325
  mode: orchestration.defaultMode,
333
326
  subagents: "not-used",
334
- reason: "Task starts in solo-first mode; use bounded subagents only for independent scout, planning, or review work.",
327
+ reason: "Parent works directly by default. One fresh read-only helper is eligible only with two independent lanes and at least 30% projected net token savings; workers and retries are disabled.",
335
328
  fieldGuidePath: orchestration.fieldGuide.enabled ? orchestration.fieldGuide.path : undefined,
336
329
  modelRoles: orchestration.roleModelGuidance
337
330
  },
@@ -355,11 +348,11 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
355
348
  ? acceptanceBaselineGuidance(written, { cwd: ctx.cwd })
356
349
  : [];
357
350
  const exactOutputGuidance = mutationPolicy === "forbidden"
358
- ? exactFinalOutputGuidance(written.summary)
351
+ ? exactFinalOutputGuidance(written)
359
352
  : [];
360
353
  const criticalProof = taskCriticalProofSection(
361
- written, plannedContext, projectFiles, acceptanceProofGuidance, isAcceptanceTestPath, acceptanceLanguageAdapterForPath
362
- );
354
+ written, plannedContext, projectFiles, acceptanceProofGuidance, isAcceptanceTestPath, acceptanceLanguageAdapterForPath,
355
+ taskPerformanceAssurance(written).requiresReview);
363
356
  bindSessionTask(ctx.cwd, sessionId, sessionName, written);
364
357
  runtimeState.cacheTaskIdentity(ctx, written);
365
358
  if (written.intakeMode !== "runtime") {
@@ -370,8 +363,8 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
370
363
  }
371
364
  const lifecycleMode = runtimeLifecycleMode(written);
372
365
  const scopeMappings = scopeResolution.mappings.map((item) => `${item.from} -> ${item.to}`);
373
- appendTrace(ctx.cwd, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", turnId: runtimeState.currentTurn(ctx)?.turnId, summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, mutationPolicy: task.mutationPolicy, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, plannedContext: plannedContext.map((item) => item.path), plannedContextComplete: plannedSelection.complete, plannedContextCandidateCount: plannedSelection.candidateCount, observedContext: observedContext.map((item) => item.path) });
374
- appendSessionTrace(pi, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", turnId: runtimeState.currentTurn(ctx)?.turnId, summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, mutationPolicy: task.mutationPolicy, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, plannedContext: plannedContext.map((item) => item.path), plannedContextComplete: plannedSelection.complete, plannedContextCandidateCount: plannedSelection.candidateCount, observedContext: observedContext.map((item) => item.path) });
366
+ appendTrace(ctx.cwd, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", turnId: runtimeState.currentTurn(ctx)?.turnId, summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, mutationPolicy: task.mutationPolicy, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, plannedContext: plannedContext.map((item) => item.path), plannedContextComplete: plannedSelection.complete, plannedContextCandidateCount: plannedSelection.candidateCount, repositoryManifestProvider: projectManifest.provider, repositoryManifestCompatibilityReason: projectManifest.compatibilityReason, observedContext: observedContext.map((item) => item.path) });
367
+ appendSessionTrace(pi, { taskId, taskRunId, sessionId, sessionName, attempt, event: "task_start", turnId: runtimeState.currentTurn(ctx)?.turnId, summary: task.summary, riskLane: params.riskLane, intakeMode: task.intakeMode, changeMode: task.changeMode, mutationPolicy: task.mutationPolicy, lifecycleMode, criterionGraphMode: written.criterionGraph.mode, criterionGraphDigest: written.criterionGraph.graphDigest, authorityProfile: written.authoritySnapshot.profile, authoritySnapshotDigest: written.authoritySnapshot.snapshotDigest, scopeMappings, plannedContext: plannedContext.map((item) => item.path), plannedContextComplete: plannedSelection.complete, plannedContextCandidateCount: plannedSelection.candidateCount, repositoryManifestProvider: projectManifest.provider, repositoryManifestCompatibilityReason: projectManifest.compatibilityReason, observedContext: observedContext.map((item) => item.path) });
375
368
  telemetry(ctx, { event: "turn_task_bound", turnId: runtimeState.currentTurn(ctx)?.turnId, taskRunId });
376
369
  recordTaskStartCheckpoint(ctx, written, firstReady.id, lifecycleMode);
377
370
  return {
@@ -379,7 +372,13 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
379
372
  type: "text",
380
373
  text: [
381
374
  `Task ${taskId} started (${params.riskLane}, ${lifecycleMode}; attempt ${attempt}/${maxAttempts}).`,
382
- ...(scopeMappings.length > 0 ? [`Canonical scope: ${scopeMappings.join("; ")}.`] : []),
375
+ ...(scopeMappings.length > 0 ? [`Initial focus mapping: ${scopeMappings.join("; ")}.`] : []),
376
+ ...(scopeResolution.ambiguous.length > 0
377
+ ? [`Ambiguous focus retained as advisory: ${scopeResolution.ambiguous.map((item) => item.input).join(", ")}.`]
378
+ : []),
379
+ ...(scopeResolution.unmatched.length > 0
380
+ ? [`Unmatched focus retained for discovery or new files: ${scopeResolution.unmatched.join(", ")}.`]
381
+ : []),
383
382
  written.verifyCommands.length > 0
384
383
  ? ["Exact verifier commands:", ...verifierCommandInstructions(written.verifyCommands)].join("\n")
385
384
  : "Verify: none (read-only).",
@@ -423,7 +422,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
423
422
  if (active?.trace.outcome === "pending") return undefined;
424
423
  const summary = redactText(automaticTaskSummary(prompt));
425
424
  const sessionName = currentSessionName(ctx);
426
- const projectManifest = repositoryFileManifestDetails(ctx.cwd), projectFiles = projectManifest.files;
425
+ const projectManifest = repositoryManifestProvider.read(ctx.cwd), projectFiles = projectManifest.files;
427
426
  const scope = intakeMode === "read-only"
428
427
  ? automaticReadOnlyTaskScope(prompt, runtimeState.preTaskContext(ctx))
429
428
  : automaticTaskScope(prompt, runtimeState.preTaskContext(ctx), projectFiles);
@@ -431,7 +430,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
431
430
  `runtime-intake-${ctx.sessionManager.getSessionId()}`,
432
431
  {
433
432
  taskId: active && active.trace.outcome !== "pending" ? summary : hasOperatorSessionName(sessionName) ? sessionName : summary,
434
- summary,
433
+ summary, operatorRequest: prompt,
435
434
  riskLane: automaticTaskRiskLane(prompt),
436
435
  intakeMode: "runtime",
437
436
  changeMode: intakeMode,
@@ -469,9 +468,10 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
469
468
  const baselineGuidance = task.changeMode === "source-change" && task.mutationPolicy !== "forbidden"
470
469
  ? acceptanceBaselineGuidance(task, { cwd: ctx.cwd })
471
470
  : [];
472
- const exactOutputGuidance = task.changeMode === "read-only" || task.mutationPolicy === "forbidden" ? exactFinalOutputGuidance(task.summary) : [];
471
+ const exactOutputGuidance = task.changeMode === "read-only" || task.mutationPolicy === "forbidden" ? exactFinalOutputGuidance(task) : [];
473
472
  const criticalProof = taskCriticalProofSection(
474
- task, plannedContext, projectFiles, acceptanceProofGuidance, isAcceptanceTestPath, acceptanceLanguageAdapterForPath
473
+ task, plannedContext, projectFiles, acceptanceProofGuidance, isAcceptanceTestPath, acceptanceLanguageAdapterForPath,
474
+ assurance.requiresReview
475
475
  );
476
476
  return {
477
477
  started: true,
@@ -479,7 +479,7 @@ export function registerTaskStartTool(pi: ExtensionAPI, deps: Record<string, any
479
479
  plannedContext,
480
480
  plannedContextComplete: plannedSelection.complete,
481
481
  text: boundedRuntimeIntakeMessage([
482
- `Piagent runtime task: ${task.taskId}; scope: ${task.scope.join(", ")}.`,
482
+ `Piagent runtime task: ${task.taskId}; initial focus (advisory): ${task.scope.join(", ")}.`,
483
483
  "The complete operator request above is the authoritative acceptance contract; runtime keeps its full criteria, so do not restate or re-scout it.",
484
484
  `Assurance: ${assurance.tier} (${assurance.reasonCodes.join(", ") || "bounded-runtime"}).`,
485
485
  ...criticalProof,
@@ -6,10 +6,24 @@ export const CONTEXT_COMPACT_PERCENT = 70;
6
6
  export const CONTEXT_FRESH_PERCENT = 82;
7
7
  export const LONG_INPUT_CHARS = 8000;
8
8
  export const MAX_INLINE_COLLAPSED_TASK_CHARS = 2200;
9
- export const RUNTIME_INTAKE_MESSAGE_MAX_CHARS = 6_000;
10
- export const SEMANTIC_COMPACTION_MAX_CHARS = 8_000;
9
+ export const RUNTIME_INTAKE_COMPACT_CHARS = 3_500;
10
+ export const RUNTIME_INTAKE_MESSAGE_MAX_CHARS = 3_500;
11
+ export const SEMANTIC_COMPACTION_MAX_CHARS = 12_000;
11
12
  export const CONTEXT_PACK_MAX_TOKENS = 900;
12
13
 
14
+ // The host's default compaction reserve is primarily an overflow guard. Piagent's
15
+ // governor acts earlier because repeatedly replaying a valid 200k+ context can
16
+ // burn substantially more tokens than the task itself. These are working-set
17
+ // limits, not capability limits: high-value task truth is carried forward while
18
+ // stale tool transcripts remain in the durable session history.
19
+ export const CONTEXT_PROVIDER_PROMPT_CEILING_TOKENS = 240_000;
20
+ export const CONTEXT_GOVERNOR_PRESSURE_TOKENS = 160_000;
21
+ export const CONTEXT_GOVERNOR_TARGET_MESSAGE_TOKENS = 72_000;
22
+ export const CONTEXT_GOVERNOR_RECENT_MESSAGE_TOKENS = 40_000;
23
+ export const CONTEXT_GOVERNOR_SEMANTIC_BOUNDARY_TOKENS = 48_000;
24
+ export const CONTEXT_GOVERNOR_TOOL_ROUND_LIMIT = 24;
25
+ export const CONTEXT_GOVERNOR_LEDGER_MAX_CHARS = 12_000;
26
+
13
27
  export const TOOL_RESULT_COMPACT_CHAR_THRESHOLD = 12_000;
14
28
  export const TOOL_RESULT_COMPACT_LINE_THRESHOLD = 180;
15
29
  export const TOOL_RESULT_PREVIEW_HEAD_LINES = 24;