@piagent/platform 1.2.10 → 1.2.11

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 (105) hide show
  1. package/CHANGELOG.md +137 -0
  2. package/README.md +27 -4
  3. package/adapters/backend-api/profile.json +1 -1
  4. package/adapters/be-readonly-fe/profile.json +2 -2
  5. package/adapters/data/profile.json +1 -1
  6. package/adapters/devops/profile.json +1 -3
  7. package/adapters/docs/profile.json +1 -1
  8. package/adapters/fullstack/profile.json +2 -4
  9. package/adapters/generic/profile.json +1 -1
  10. package/adapters/mobile/profile.json +1 -2
  11. package/adapters/node-typescript/profile.json +1 -3
  12. package/benchmarks/core-v1/suite.json +51 -0
  13. package/benchmarks/core-v1/tasks/discount-order/grade.mjs +17 -0
  14. package/benchmarks/core-v1/tasks/discount-order/project/package.json +8 -0
  15. package/benchmarks/core-v1/tasks/discount-order/project/src/discount.js +3 -0
  16. package/benchmarks/core-v1/tasks/discount-order/project/src/order.js +6 -0
  17. package/benchmarks/core-v1/tasks/discount-order/project/test/order.test.js +7 -0
  18. package/benchmarks/core-v1/tasks/discount-order/prompt.md +4 -0
  19. package/benchmarks/core-v1/tasks/invoice-quantity/grade.mjs +17 -0
  20. package/benchmarks/core-v1/tasks/invoice-quantity/project/package.json +8 -0
  21. package/benchmarks/core-v1/tasks/invoice-quantity/project/src/invoice.js +3 -0
  22. package/benchmarks/core-v1/tasks/invoice-quantity/project/test/invoice.test.js +7 -0
  23. package/benchmarks/core-v1/tasks/invoice-quantity/prompt.md +3 -0
  24. package/benchmarks/core-v1/tasks/protected-env-refusal/grade.mjs +11 -0
  25. package/benchmarks/core-v1/tasks/protected-env-refusal/project/README.md +4 -0
  26. package/benchmarks/core-v1/tasks/protected-env-refusal/project/package.json +8 -0
  27. package/benchmarks/core-v1/tasks/protected-env-refusal/project/test/smoke.test.js +4 -0
  28. package/benchmarks/core-v1/tasks/protected-env-refusal/prompt.md +4 -0
  29. package/benchmarks/core-v1/tasks/targeted-session/grade.mjs +14 -0
  30. package/benchmarks/core-v1/tasks/targeted-session/project/package.json +8 -0
  31. package/benchmarks/core-v1/tasks/targeted-session/project/src/auth/session.js +3 -0
  32. package/benchmarks/core-v1/tasks/targeted-session/project/src/billing/currency.js +3 -0
  33. package/benchmarks/core-v1/tasks/targeted-session/project/src/catalog/search.js +3 -0
  34. package/benchmarks/core-v1/tasks/targeted-session/project/src/notifications/channel.js +3 -0
  35. package/benchmarks/core-v1/tasks/targeted-session/project/src/search/tokenize.js +3 -0
  36. package/benchmarks/core-v1/tasks/targeted-session/project/test/session.test.js +7 -0
  37. package/benchmarks/core-v1/tasks/targeted-session/prompt.md +4 -0
  38. package/catalog/capabilities.json +10 -10
  39. package/docs/command-reference-vietnamese.md +10 -6
  40. package/docs/context-engine.md +33 -11
  41. package/docs/distribution-standard.md +11 -8
  42. package/docs/mcp-and-tools.md +13 -7
  43. package/docs/model-options.md +7 -10
  44. package/docs/operator-manual-vietnamese.md +82 -33
  45. package/docs/package-architecture-notes.md +3 -1
  46. package/docs/publishing-for-teams.md +4 -0
  47. package/docs/quality-benchmark.md +225 -58
  48. package/docs/quickstart-vietnamese.md +5 -0
  49. package/docs/release-install-policy.md +41 -7
  50. package/docs/runtime-harness-standard.md +47 -29
  51. package/docs/runtime-policy-design.md +23 -12
  52. package/docs/runtime-quality-baseline.md +31 -17
  53. package/docs/security-threat-model.md +1 -1
  54. package/docs/task-implementation-contract.md +113 -177
  55. package/docs/task-lifecycle-vietnamese.md +129 -125
  56. package/docs/team-onboarding.md +12 -4
  57. package/docs/usage-observability.md +15 -8
  58. package/docs-site/architecture.html +1 -1
  59. package/docs-site/commands.html +1 -1
  60. package/docs-site/content/runtime.html +10 -0
  61. package/docs-site/context-engine.html +1 -1
  62. package/docs-site/index.html +1 -1
  63. package/docs-site/mcp-approval.html +1 -1
  64. package/docs-site/mcp-auth.html +1 -1
  65. package/docs-site/mcp-servers.html +1 -1
  66. package/docs-site/mcp.html +1 -1
  67. package/docs-site/permissions.html +1 -1
  68. package/docs-site/profiles.html +1 -1
  69. package/docs-site/quickstart.html +1 -1
  70. package/docs-site/runtime.html +11 -1
  71. package/docs-site/scope.html +1 -1
  72. package/docs-site/security.html +1 -1
  73. package/docs-site/team.html +1 -1
  74. package/docs-site/workflows.html +1 -1
  75. package/evals/fixtures/task-contract.invalid.json +15 -1
  76. package/evals/fixtures/task-contract.valid.json +18 -2
  77. package/package.json +3 -2
  78. package/packages/piagent-core/README.md +37 -3
  79. package/packages/piagent-core/benchmark/benchmark-core.js +691 -0
  80. package/packages/piagent-core/extensions/context-engine.js +81 -57
  81. package/packages/piagent-core/extensions/guard-types.ts +35 -3
  82. package/packages/piagent-core/extensions/local-state-path.js +59 -0
  83. package/packages/piagent-core/extensions/piagent-guard.ts +1865 -171
  84. package/packages/piagent-core/extensions/policy-core.js +11 -1
  85. package/packages/piagent-core/extensions/runtime-evidence.js +39 -19
  86. package/packages/piagent-core/extensions/state-retention.js +218 -0
  87. package/packages/piagent-core/extensions/task-lifecycle.js +138 -0
  88. package/packages/piagent-core/extensions/task-state.js +630 -0
  89. package/packages/piagent-core/package.json +1 -1
  90. package/packages/piagent-core/policies/base-policy.json +1 -0
  91. package/packages/piagent-core/prompts/be-to-fe.md +14 -22
  92. package/packages/piagent-core/prompts/platform-improve.md +12 -17
  93. package/packages/piagent-core/prompts/review.md +7 -11
  94. package/packages/piagent-core/prompts/scout.md +6 -10
  95. package/packages/piagent-core/prompts/task.md +11 -17
  96. package/packages/piagent-core/skills/piagent-ops/SKILL.md +12 -15
  97. package/schemas/task-contract.schema.json +267 -104
  98. package/scripts/benchmark-runner.mjs +1172 -0
  99. package/scripts/install-global.sh +1 -1
  100. package/scripts/migrate-project-state.mjs +94 -3
  101. package/scripts/piagent-cli.mjs +1 -1
  102. package/scripts/update-global.mjs +36 -3
  103. package/scripts/verify-local.sh +15 -0
  104. package/templates/project/.pi/task-contract.template.json +19 -2
  105. package/templates/project/AGENTS.md +10 -20
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
  usage() {
5
5
  cat <<'USAGE'
6
6
  Usage:
7
- scripts/install-global.sh [--stable|--dev|--local|--channel <stable|dev|local>] [--version <tag>] [--resolve-tag] [--package-source <source>] [--dry-run] [--with-mcp|--no-mcp] [--mcp-preset <preset>] [--with-subagents|--no-subagents] [--subagents-preset <preset>] [--with-web-access|--no-web-access] [--with-herdr] [--model-scope <preset>]
7
+ scripts/install-global.sh [--stable|--dev|--local|--channel <stable|dev|local>] [--version <tag>] [--resolve-tag] [--package-source <source>] [--dry-run] [--with-mcp|--no-mcp] [--mcp-preset <preset>] [--with-subagents|--no-subagents] [--subagents-preset <preset>] [--with-web-access|--no-web-access] [--with-herdr] [--model-scope <preset>|--no-model-scope]
8
8
 
9
9
  Purpose:
10
10
  Install the piagent Pi package into the current user's global Pi settings.
@@ -7,6 +7,15 @@
7
7
  // the caller confirms removal, so an interrupted run is always recoverable.
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
+ import crypto from "node:crypto";
11
+ import { migrateTaskState, taskStateMigrationStatus } from "../packages/piagent-core/extensions/task-state.js";
12
+
13
+ const TASK_CONTRACT_MIGRATION_ID = "task-contract-v2";
14
+ const AGENTS_MANAGED_START = "<!-- piagent-managed:start -->";
15
+ const AGENTS_MANAGED_END = "<!-- piagent-managed:end -->";
16
+ const LEGACY_GENERATED_AGENTS_HASHES = new Set([
17
+ "571fbf7967ce36a0c28fbc703551b6e8ad113933e8de0ba745c69b971eb73fb1"
18
+ ]);
10
19
 
11
20
  const RENAMES = [
12
21
  { from: ".pi/company-profile.json", to: ".pi/piagent-profile.json" },
@@ -71,6 +80,38 @@ function rewriteText(text) {
71
80
  return output;
72
81
  }
73
82
 
83
+ function sha256(text) {
84
+ return crypto.createHash("sha256").update(text).digest("hex");
85
+ }
86
+
87
+ function managedAgentsBlock(text) {
88
+ const start = text.indexOf(AGENTS_MANAGED_START);
89
+ const endStart = text.indexOf(AGENTS_MANAGED_END, start + AGENTS_MANAGED_START.length);
90
+ if (start < 0 || endStart < 0) return undefined;
91
+ return { start, end: endStart + AGENTS_MANAGED_END.length };
92
+ }
93
+
94
+ function currentAgentsTemplate() {
95
+ try {
96
+ return fs.readFileSync(path.resolve(import.meta.dirname, "../templates/project/AGENTS.md"), "utf8");
97
+ } catch {
98
+ return undefined;
99
+ }
100
+ }
101
+
102
+ function migrateAgentsText(text) {
103
+ const renamed = rewriteText(text);
104
+ const template = currentAgentsTemplate();
105
+ if (!template) return renamed;
106
+ if (LEGACY_GENERATED_AGENTS_HASHES.has(sha256(renamed))) return template;
107
+
108
+ const existingBlock = managedAgentsBlock(renamed);
109
+ const templateBlock = managedAgentsBlock(template);
110
+ if (!existingBlock || !templateBlock) return renamed;
111
+ const replacement = template.slice(templateBlock.start, templateBlock.end);
112
+ return `${renamed.slice(0, existingBlock.start)}${replacement}${renamed.slice(existingBlock.end)}`;
113
+ }
114
+
74
115
  function copyRecursive(from, to) {
75
116
  const stat = fs.lstatSync(from);
76
117
  if (stat.isSymbolicLink()) return { skipped: from, reason: "symlink" };
@@ -110,12 +151,19 @@ for (const { from, to } of RENAMES) {
110
151
  // that no longer exist.
111
152
  const agentsPath = path.join(projectPath, "AGENTS.md");
112
153
  let agentsNeedsRewrite = false;
154
+ let migratedAgentsText;
113
155
  if (fs.existsSync(agentsPath)) {
114
156
  const text = fs.readFileSync(agentsPath, "utf8");
115
- agentsNeedsRewrite = rewriteText(text) !== text;
157
+ migratedAgentsText = migrateAgentsText(text);
158
+ agentsNeedsRewrite = migratedAgentsText !== text;
116
159
  }
117
160
 
118
- const nothingToDo = planned.length === 0 && alreadyMigrated.length === 0 && !agentsNeedsRewrite;
161
+ const taskMigrationBefore = taskStateMigrationStatus(projectPath);
162
+ const nothingToDo = planned.length === 0
163
+ && alreadyMigrated.length === 0
164
+ && !agentsNeedsRewrite
165
+ && taskMigrationBefore.legacy === 0
166
+ && taskMigrationBefore.unreadable.length === 0;
119
167
 
120
168
  if (nothingToDo) {
121
169
  console.log(JSON.stringify({ ok: true, projectPath, migrated: false, reason: "already on the current layout" }, null, 2));
@@ -129,6 +177,8 @@ if (!apply) {
129
177
  dryRun: true,
130
178
  wouldRename: planned,
131
179
  wouldRewrite: agentsNeedsRewrite ? ["AGENTS.md"] : [],
180
+ wouldMigrateTaskContracts: taskMigrationBefore.legacy,
181
+ taskStateWarnings: taskMigrationBefore.unreadable,
132
182
  alreadyMigrated,
133
183
  next: alreadyMigrated.length > 0 && planned.length === 0
134
184
  ? "re-run with --apply --remove-old to delete the originals"
@@ -137,6 +187,17 @@ if (!apply) {
137
187
  process.exit(0);
138
188
  }
139
189
 
190
+ if (taskMigrationBefore.unreadable.length > 0) {
191
+ console.log(JSON.stringify({
192
+ ok: false,
193
+ projectPath,
194
+ migrated: false,
195
+ taskStateWarnings: taskMigrationBefore.unreadable,
196
+ reason: "invalid task state requires manual recovery; no project files were changed"
197
+ }, null, 2));
198
+ process.exit(2);
199
+ }
200
+
140
201
  const renamed = [];
141
202
  for (const { from, to } of planned) {
142
203
  const result = copyRecursive(path.join(projectPath, from), path.join(projectPath, to));
@@ -148,7 +209,36 @@ for (const { from, to } of planned) {
148
209
  }
149
210
 
150
211
  if (agentsNeedsRewrite) {
151
- fs.writeFileSync(agentsPath, rewriteText(fs.readFileSync(agentsPath, "utf8")));
212
+ fs.writeFileSync(agentsPath, migratedAgentsText);
213
+ }
214
+
215
+ const taskMigration = migrateTaskState(projectPath);
216
+ if (taskMigration.warnings.length > 0) {
217
+ console.log(JSON.stringify({
218
+ ok: false,
219
+ projectPath,
220
+ migrated: false,
221
+ renamed,
222
+ taskMigration,
223
+ reason: "invalid task state requires manual recovery; old project paths were preserved"
224
+ }, null, 2));
225
+ process.exit(2);
226
+ }
227
+ if (taskMigration.migrated > 0) {
228
+ const migrationFile = path.join(projectPath, ".pi", "piagent-state", "migrations.json");
229
+ let migrationState = { schemaVersion: 1, applied: [] };
230
+ try {
231
+ const parsed = JSON.parse(fs.readFileSync(migrationFile, "utf8"));
232
+ if (parsed && typeof parsed === "object" && Array.isArray(parsed.applied)) migrationState = parsed;
233
+ } catch {
234
+ // Missing or unreadable migration metadata is reconstructed from applied work.
235
+ }
236
+ const applied = migrationState.applied.filter((entry) => entry?.id !== TASK_CONTRACT_MIGRATION_ID);
237
+ applied.push({ id: TASK_CONTRACT_MIGRATION_ID, appliedAt: new Date().toISOString(), migrated: taskMigration.migrated });
238
+ fs.mkdirSync(path.dirname(migrationFile), { recursive: true, mode: 0o700 });
239
+ const temporary = `${migrationFile}.${process.pid}.tmp`;
240
+ fs.writeFileSync(temporary, `${JSON.stringify({ schemaVersion: 1, applied }, null, 2)}\n`, { mode: 0o600 });
241
+ fs.renameSync(temporary, migrationFile);
152
242
  }
153
243
 
154
244
  const removed = [];
@@ -168,6 +258,7 @@ console.log(JSON.stringify({
168
258
  renamed,
169
259
  alreadyMigrated,
170
260
  rewrote: agentsNeedsRewrite ? ["AGENTS.md"] : [],
261
+ taskMigration,
171
262
  skipped,
172
263
  removedOld: removed,
173
264
  next: pendingCleanup > 0
@@ -10,7 +10,7 @@ const scriptByCommand = {
10
10
  "piagent-uninstall": "scripts/uninstall-global.sh",
11
11
  "piagent-init": "scripts/init-project.sh",
12
12
  "piagent-doctor": "scripts/team-doctor.sh",
13
- "piagent-benchmark": "scripts/quality-benchmark.sh",
13
+ "piagent-benchmark": "scripts/benchmark-runner.mjs",
14
14
  "piagent-usage": "scripts/pi-session-stats.sh",
15
15
  "piagent-models": "scripts/pi-model-catalog.sh",
16
16
  "piagent-model-scope": "scripts/configure-model-scope.sh",
@@ -213,6 +213,16 @@ function binForPrefix(prefix) {
213
213
  return process.platform === "win32" ? prefix : path.join(prefix, "bin");
214
214
  }
215
215
 
216
+ function npmPrefixForInstalledHelper(root) {
217
+ if (path.basename(root) !== "platform") return undefined;
218
+ const scopeRoot = path.dirname(root);
219
+ if (path.basename(scopeRoot) !== "@piagent") return undefined;
220
+ const nodeModulesRoot = path.dirname(scopeRoot);
221
+ if (path.basename(nodeModulesRoot) !== "node_modules") return undefined;
222
+ const parent = path.dirname(nodeModulesRoot);
223
+ return path.basename(parent) === "lib" ? path.dirname(parent) : parent;
224
+ }
225
+
216
226
  function prependPath(directory) {
217
227
  process.env.PATH = `${directory}${path.delimiter}${process.env.PATH ?? ""}`;
218
228
  }
@@ -231,6 +241,23 @@ function resolveNpmInstallTarget(options, needsGlobalInstall) {
231
241
 
232
242
  const defaultPrefix = configuredNpmPrefix();
233
243
  const defaultRoot = npmRoot(defaultPrefix);
244
+ const activePrefix = runningFromGlobalInstall() ? npmPrefixForInstalledHelper(platformRoot) : undefined;
245
+ if (
246
+ needsGlobalInstall
247
+ && activePrefix
248
+ && path.resolve(activePrefix) !== path.resolve(defaultPrefix ?? "")
249
+ ) {
250
+ const activeRoot = npmRoot(activePrefix);
251
+ if (activeRoot && canWriteOrCreate(activeRoot)) {
252
+ return {
253
+ prefix: activePrefix,
254
+ root: activeRoot,
255
+ bin: binForPrefix(activePrefix),
256
+ reason: "active-install",
257
+ configuredPrefix: defaultPrefix
258
+ };
259
+ }
260
+ }
234
261
  if (!needsGlobalInstall || (defaultRoot && canWriteOrCreate(defaultRoot))) {
235
262
  return { prefix: undefined, root: defaultRoot, bin: undefined, reason: "default" };
236
263
  }
@@ -289,15 +316,17 @@ function summarizeMigration(report, dryRun) {
289
316
  const rewrote = report.rewrote?.length ?? report.wouldRewrite?.length ?? 0;
290
317
  const wouldRename = report.wouldRename?.length ?? 0;
291
318
  const alreadyMigrated = report.alreadyMigrated?.length ?? 0;
319
+ const wouldMigrateTasks = report.wouldMigrateTaskContracts ?? 0;
320
+ const migratedTasks = report.taskMigration?.migrated ?? 0;
292
321
 
293
322
  if (dryRun) {
294
- const planned = wouldRename + rewrote + alreadyMigrated;
323
+ const planned = wouldRename + rewrote + alreadyMigrated + wouldMigrateTasks;
295
324
  return planned > 0
296
- ? `project migration: would update legacy layout (${wouldRename} rename, ${rewrote} rewrite, ${alreadyMigrated} already copied)`
325
+ ? `project migration: would update legacy layout (${wouldRename} rename, ${rewrote} rewrite, ${alreadyMigrated} already copied, ${wouldMigrateTasks} task contract)`
297
326
  : "project migration: already current";
298
327
  }
299
328
  if (report.migrated === false) return "project migration: already current";
300
- return `project migration: applied (${renamed} rename, ${rewrote} rewrite, ${removed} old path removed)`;
329
+ return `project migration: applied (${renamed} rename, ${rewrote} rewrite, ${removed} old path removed, ${migratedTasks} task contract)`;
301
330
  }
302
331
 
303
332
  function runProjectMigration(project, options, activePlatformRoot) {
@@ -315,6 +344,8 @@ function runProjectMigration(project, options, activePlatformRoot) {
315
344
  if ((report.skipped?.length ?? 0) > 0) {
316
345
  fail(`project migration skipped protected entries: ${report.skipped.map((entry) => `${entry.path} (${entry.reason})`).join(", ")}`);
317
346
  }
347
+ const stateWarnings = [...(report.taskStateWarnings ?? []), ...(report.taskMigration?.warnings ?? [])];
348
+ if (stateWarnings.length > 0) fail(`project migration found invalid task state: ${stateWarnings.join("; ")}`);
318
349
  console.log(` ${summarizeMigration(report, options.dryRun)}`);
319
350
  }
320
351
 
@@ -407,6 +438,8 @@ function main() {
407
438
  if (npmTarget.bin) prependPath(npmTarget.bin);
408
439
  if (npmTarget.reason === "user-prefix") {
409
440
  console.log(` npm: default global root is not writable (${npmTarget.blockedRoot ?? "unknown"}); using ${npmTarget.prefix}`);
441
+ } else if (npmTarget.reason === "active-install") {
442
+ console.log(` npm: active helper is installed under ${npmTarget.prefix}; keeping host and helper in that prefix`);
410
443
  } else if (npmTarget.reason === "explicit") {
411
444
  console.log(` npm: using explicit global prefix ${npmTarget.prefix}`);
412
445
  }
@@ -53,9 +53,12 @@ required_files=(
53
53
  "$ROOT/packages/piagent-core/extensions/piagent-guard.ts"
54
54
  "$ROOT/packages/piagent-core/extensions/context-engine.js"
55
55
  "$ROOT/packages/piagent-core/extensions/context-index-policy.js"
56
+ "$ROOT/packages/piagent-core/extensions/local-state-path.js"
56
57
  "$ROOT/packages/piagent-core/extensions/policy-core.js"
57
58
  "$ROOT/packages/piagent-core/extensions/redaction-core.js"
58
59
  "$ROOT/packages/piagent-core/extensions/runtime-evidence.js"
60
+ "$ROOT/packages/piagent-core/extensions/state-retention.js"
61
+ "$ROOT/packages/piagent-core/extensions/task-state.js"
59
62
  "$ROOT/packages/piagent-core/security/sensitive-data.js"
60
63
  "$ROOT/packages/piagent-core/capabilities/capability-core.js"
61
64
  "$ROOT/packages/piagent-core/prompts/platform-improve.md"
@@ -162,6 +165,7 @@ required_files=(
162
165
  "$ROOT/scripts/team-doctor.sh"
163
166
  "$ROOT/scripts/link-project.sh"
164
167
  "$ROOT/scripts/profile-doctor.sh"
168
+ "$ROOT/scripts/benchmark-runner.mjs"
165
169
  "$ROOT/scripts/quality-benchmark.sh"
166
170
  "$ROOT/scripts/runtime-policy-smoke.sh"
167
171
  "$ROOT/scripts/pi-session-stats.sh"
@@ -177,6 +181,9 @@ required_files=(
177
181
  "$ROOT/tests/capability-core.test.mjs"
178
182
  "$ROOT/tests/piagent-guard-integration.test.mjs"
179
183
  "$ROOT/tests/context-engine.test.mjs"
184
+ "$ROOT/tests/benchmark-core.test.mjs"
185
+ "$ROOT/tests/benchmark-runner.test.mjs"
186
+ "$ROOT/tests/benchmark-suite.test.mjs"
180
187
  "$ROOT/tests/workflow-prompts.test.mjs"
181
188
  "$ROOT/tests/install-global.test.mjs"
182
189
  "$ROOT/tests/package-distribution.test.mjs"
@@ -185,6 +192,8 @@ required_files=(
185
192
  "$ROOT/tests/redaction-core.test.mjs"
186
193
  "$ROOT/tests/runtime-evidence.test.mjs"
187
194
  "$ROOT/tests/golden-enforcement.test.mjs"
195
+ "$ROOT/packages/piagent-core/benchmark/benchmark-core.js"
196
+ "$ROOT/benchmarks/core-v1/suite.json"
188
197
  "$ROOT/tests/capability-sources.test.mjs"
189
198
  "$ROOT/packages/piagent-core/capabilities/capability-sources.js"
190
199
  "$ROOT/packages/piagent-core/extensions/guard-shell-analysis.ts"
@@ -473,6 +482,7 @@ require_documented "piagent-task-trace" "$ROOT/packages/piagent-core/extensions/
473
482
  require_documented "piagent-source-cache" "$ROOT/packages/piagent-core/skills" "$ROOT/templates/project/AGENTS.md"
474
483
  require_documented "piagent_source_checkout" "$ROOT/packages/piagent-core"
475
484
  require_documented "scripts/setup.sh" "$ROOT/README.md" "$ROOT/docs"
485
+ require_documented "piagent-benchmark" "$ROOT/README.md" "$ROOT/docs"
476
486
  require_documented "quality-benchmark.sh" "$ROOT/README.md" "$ROOT/docs"
477
487
  require_documented "piagent-capabilities" "$ROOT/README.md" "$ROOT/docs/capability-packs.md"
478
488
  require_documented ".pi-subagents/" "$ROOT/.gitignore" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/docs/distribution-standard.md" "$ROOT/scripts/init-project.sh"
@@ -547,14 +557,19 @@ fi
547
557
  node --check "$ROOT/packages/piagent-core/extensions/piagent-guard.ts" >/dev/null
548
558
  node --check "$ROOT/packages/piagent-core/extensions/context-engine.js" >/dev/null
549
559
  node --check "$ROOT/packages/piagent-core/extensions/context-index-policy.js" >/dev/null
560
+ node --check "$ROOT/packages/piagent-core/extensions/local-state-path.js" >/dev/null
550
561
  node --check "$ROOT/packages/piagent-core/extensions/policy-core.js" >/dev/null
551
562
  node --check "$ROOT/packages/piagent-core/extensions/redaction-core.js" >/dev/null
552
563
  node --check "$ROOT/packages/piagent-core/extensions/runtime-evidence.js" >/dev/null
564
+ node --check "$ROOT/packages/piagent-core/extensions/state-retention.js" >/dev/null
565
+ node --check "$ROOT/packages/piagent-core/extensions/task-state.js" >/dev/null
566
+ node --check "$ROOT/packages/piagent-core/benchmark/benchmark-core.js" >/dev/null
553
567
  node --check "$ROOT/packages/piagent-core/security/sensitive-data.js" >/dev/null
554
568
  node --check "$ROOT/packages/piagent-core/capabilities/capability-core.js" >/dev/null
555
569
  node --check "$ROOT/packages/piagent-core/capabilities/capability-sources.js" >/dev/null
556
570
  node --check "$ROOT/scripts/capability-catalog.mjs" >/dev/null
557
571
  node --check "$ROOT/scripts/piagent-cli.mjs" >/dev/null
572
+ node --check "$ROOT/scripts/benchmark-runner.mjs" >/dev/null
558
573
  node --check "$ROOT/scripts/context-engine.mjs" >/dev/null
559
574
  node --check "$ROOT/scripts/pi-usage-history.mjs" >/dev/null
560
575
  node --check "$ROOT/scripts/migrate-project-state.mjs" >/dev/null
@@ -1,7 +1,16 @@
1
1
  {
2
- "taskId": "TASK-0001",
2
+ "schemaVersion": 2,
3
+ "taskRunId": "task-0001-20260731120000-a1b2c3d4e5",
4
+ "taskId": "task-0001",
5
+ "sessionId": "pi-session-example",
6
+ "sessionName": "TASK-0001 Example task",
7
+ "changeMode": "source-change",
8
+ "attempt": 1,
9
+ "maxAttempts": 3,
10
+ "previousAttempts": [],
3
11
  "summary": "Replace with one-sentence task outcome.",
4
12
  "riskLane": "normal",
13
+ "intakeMode": "runtime",
5
14
  "expectedOutput": "Replace with exact artifact or behavior expected.",
6
15
  "acceptanceCriteria": [
7
16
  "Replace with pass/fail criterion."
@@ -17,6 +26,7 @@
17
26
  "contextManifest": [],
18
27
  "memoryCitations": [],
19
28
  "mcpCapabilities": [],
29
+ "verifyGroup": "source",
20
30
  "verifyCommands": [
21
31
  "Replace with verify command."
22
32
  ],
@@ -66,9 +76,16 @@
66
76
  "watchdog": "Use a strong model only for final risk review, security, release, or high-impact changes."
67
77
  }
68
78
  },
79
+ "baselineChangedFiles": [],
80
+ "baselineFileDigests": {},
81
+ "observedChangedFiles": [],
82
+ "finalWorkingTreeFiles": [],
83
+ "finalFileDigests": {},
69
84
  "changedFiles": [],
70
85
  "verifyEvidence": [],
71
86
  "trace": {
72
87
  "outcome": "pending"
73
- }
88
+ },
89
+ "createdAt": "2026-07-31T12:00:00.000Z",
90
+ "updatedAt": "2026-07-31T12:00:00.000Z"
74
91
  }
@@ -1,29 +1,19 @@
1
1
  # Project Agent Instructions
2
2
 
3
+ <!-- piagent-managed:start -->
3
4
  ## Operating model
4
5
 
5
6
  This project uses Pi Agent Platform.
6
7
 
7
- Before implementation:
8
-
9
- 1. Load `.pi/piagent-profile.json` with `piagent_context`.
10
- 2. If `.pi/project-context.md` still says "Generated: not yet", run `/onboard run` after login/model selection before the first implementation task.
11
- 3. Check `.pi/context-index.json` with `/context index` or `piagent_context_index_status` when available; use it only as an advisory navigation map.
12
- 4. Read `.pi/project-context.md` and required context files listed in the profile; use `piagent_context_budget` for large files.
13
- 5. Check project memory with `piagent_memory_status` when relevant; memory is advisory, source files are authoritative.
14
- 6. Start source-changing work with `piagent_task_start`.
15
- 7. Respect protected paths.
16
- 8. Use `piagent_exec_policy_check` before high-impact or complex shell commands.
17
- 9. Use `piagent_tool_policy_check` before non-piagent MCP/app tools.
18
- 10. Use MCP/tools only when declared in profile.
19
- 11. Use `piagent_usage_snapshot` or `/usage` when the user asks about token/context usage or session follow-up.
20
- 12. Record context/verify/trace with `piagent_context_record`, `piagent_verify_record`, and `piagent_trace_record`. Passing verify evidence must be the exact command from `task.verifyCommands`.
21
- 13. Run `piagent_task_gate_check` before DONE.
22
- 14. For unclear tasks, use `/workflow discuss` first; do not implement while requirements are unresolved.
23
- 15. For external source repos, use `piagent-source-cache` and read targeted files only.
24
- 16. For medium/large tasks, auto-delegate independent read-only scout/planning/review work to `piagent-scout`, `piagent-planner`, `piagent-reviewer`, or `piagent-oracle` when `pi-subagents` is available. Do not require the user to type `/run` for normal task orchestration.
25
- 17. Keep implementation single-writer by default. Use parallel writers only with explicit user approval or safe worktree isolation and disjoint write sets.
26
- 18. If the bundled `pi-subagents` parent skill is available, use it for delegation patterns, review loops, native supervisor coordination, and safety boundaries.
8
+ For an ordinary source task:
9
+
10
+ 1. Runtime binds bounded source work to this Pi session before the model starts. If intake pauses for broad/high-risk/ambiguous scope, call `piagent_task_start` exactly once with project-relative path/glob scope and reuse the contract.
11
+ 2. Read the narrow target and nearest test. Use ordinary read/search/edit/bash tools and one writer.
12
+ 3. Complete intended source and focused regression-test edits, then run each exact runtime verifier. Rerun only after another mutation.
13
+ 4. Do not call Piagent management/diagnostic tools unless runtime or the operator asks. Report changed files, verification, and residual risk concisely.
14
+
15
+ Runtime enforces protected paths, permissions, external/destructive confirmation, scope, current-tree evidence, and the final gate. Current source is authoritative; generated context is advisory. Use subagents only for independent read-only lanes.
16
+ <!-- piagent-managed:end -->
27
17
 
28
18
  ## Review
29
19