@piagent/platform 1.0.0

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 (159) hide show
  1. package/.gitattributes +7 -0
  2. package/AGENTS.md +31 -0
  3. package/CHANGELOG.md +296 -0
  4. package/CODE_OF_CONDUCT.md +36 -0
  5. package/CONTRIBUTING.md +66 -0
  6. package/LICENSE +21 -0
  7. package/README.md +588 -0
  8. package/SECURITY.md +38 -0
  9. package/adapters/backend-api/profile.json +88 -0
  10. package/adapters/be-readonly-fe/profile.json +120 -0
  11. package/adapters/data/profile.json +88 -0
  12. package/adapters/devops/profile.json +92 -0
  13. package/adapters/docs/profile.json +74 -0
  14. package/adapters/fullstack/profile.json +94 -0
  15. package/adapters/generic/profile.json +95 -0
  16. package/adapters/mobile/profile.json +87 -0
  17. package/adapters/node-typescript/profile.json +76 -0
  18. package/adapters/python/profile.json +75 -0
  19. package/adapters/web-frontend/profile.json +101 -0
  20. package/catalog/capabilities.json +206 -0
  21. package/docs/architecture.md +64 -0
  22. package/docs/auto-delegation-policy.md +192 -0
  23. package/docs/capability-packs.md +234 -0
  24. package/docs/command-reference-vietnamese.md +484 -0
  25. package/docs/context-window-policy.md +85 -0
  26. package/docs/distribution-standard.md +229 -0
  27. package/docs/herdr-workflow.md +58 -0
  28. package/docs/mcp-and-tools.md +316 -0
  29. package/docs/memory-policy.md +164 -0
  30. package/docs/model-options.md +165 -0
  31. package/docs/oauth-providers.md +53 -0
  32. package/docs/operator-manual-vietnamese.md +1080 -0
  33. package/docs/package-architecture-notes.md +101 -0
  34. package/docs/project-adapters.md +174 -0
  35. package/docs/project-onboarding.md +135 -0
  36. package/docs/publishing-for-teams.md +64 -0
  37. package/docs/quality-benchmark.md +74 -0
  38. package/docs/quickstart-vietnamese.md +350 -0
  39. package/docs/release-install-policy.md +223 -0
  40. package/docs/runtime-harness-standard.md +118 -0
  41. package/docs/runtime-policy-design.md +132 -0
  42. package/docs/runtime-quality-baseline.md +257 -0
  43. package/docs/security-redaction-benchmark.md +56 -0
  44. package/docs/security-threat-model.md +66 -0
  45. package/docs/subagent-orchestration-capabilities.md +104 -0
  46. package/docs/subagents-and-multiagent.md +346 -0
  47. package/docs/task-implementation-contract.md +200 -0
  48. package/docs/team-onboarding.md +333 -0
  49. package/docs/usage-observability.md +130 -0
  50. package/docs/vercel-docs-site.md +115 -0
  51. package/docs/workflow-recipes.md +125 -0
  52. package/docs-site/assets/piagent-logo.svg +35 -0
  53. package/docs-site/favicon.svg +18 -0
  54. package/docs-site/index.html +1613 -0
  55. package/docs-site/vercel.json +24 -0
  56. package/evals/fixtures/action-proposal.invalid.json +34 -0
  57. package/evals/fixtures/action-proposal.valid.json +34 -0
  58. package/evals/fixtures/capability-pack.invalid.json +123 -0
  59. package/evals/fixtures/capability-pack.valid.json +123 -0
  60. package/evals/fixtures/capability-recipe.invalid.json +81 -0
  61. package/evals/fixtures/capability-recipe.valid.json +82 -0
  62. package/evals/fixtures/context-index.invalid.json +25 -0
  63. package/evals/fixtures/context-index.valid.json +25 -0
  64. package/evals/fixtures/eval-scenario.invalid.json +40 -0
  65. package/evals/fixtures/eval-scenario.valid.json +45 -0
  66. package/evals/fixtures/project-profile.invalid.json +88 -0
  67. package/evals/fixtures/project-profile.valid.json +95 -0
  68. package/evals/fixtures/task-contract.invalid.json +73 -0
  69. package/evals/fixtures/task-contract.valid.json +74 -0
  70. package/evals/golden/enforcement-decisions.json +329 -0
  71. package/evals/scenarios/capability-resolution.json +45 -0
  72. package/package.json +132 -0
  73. package/packages/piagent-core/README.md +147 -0
  74. package/packages/piagent-core/capabilities/capability-core.js +1023 -0
  75. package/packages/piagent-core/capabilities/capability-sources.js +265 -0
  76. package/packages/piagent-core/extensions/guard-io.js +45 -0
  77. package/packages/piagent-core/extensions/guard-shell-analysis.ts +558 -0
  78. package/packages/piagent-core/extensions/guard-types.ts +406 -0
  79. package/packages/piagent-core/extensions/piagent-guard.ts +5760 -0
  80. package/packages/piagent-core/extensions/policy-core.js +1070 -0
  81. package/packages/piagent-core/extensions/redaction-core.js +4 -0
  82. package/packages/piagent-core/extensions/runtime-evidence.js +215 -0
  83. package/packages/piagent-core/package.json +46 -0
  84. package/packages/piagent-core/policies/base-policy.json +249 -0
  85. package/packages/piagent-core/prompts/be-to-fe.md +82 -0
  86. package/packages/piagent-core/prompts/commit.md +27 -0
  87. package/packages/piagent-core/prompts/discuss.md +35 -0
  88. package/packages/piagent-core/prompts/memory-policy.md +52 -0
  89. package/packages/piagent-core/prompts/model-options.md +68 -0
  90. package/packages/piagent-core/prompts/onboard-project.md +147 -0
  91. package/packages/piagent-core/prompts/piagent-commands.md +68 -0
  92. package/packages/piagent-core/prompts/plan.md +35 -0
  93. package/packages/piagent-core/prompts/platform-improve.md +69 -0
  94. package/packages/piagent-core/prompts/pr.md +26 -0
  95. package/packages/piagent-core/prompts/review.md +38 -0
  96. package/packages/piagent-core/prompts/scout.md +50 -0
  97. package/packages/piagent-core/prompts/task.md +69 -0
  98. package/packages/piagent-core/security/sensitive-data.js +187 -0
  99. package/packages/piagent-core/skills/piagent-ops/SKILL.md +44 -0
  100. package/packages/piagent-core/skills/piagent-source-cache/SKILL.md +59 -0
  101. package/packages/piagent-core/skills/piagent-source-cache/checkout-source-repo.sh +144 -0
  102. package/packages/piagent-core/subagents/piagent-oracle.md +29 -0
  103. package/packages/piagent-core/subagents/piagent-planner.md +46 -0
  104. package/packages/piagent-core/subagents/piagent-reviewer.md +48 -0
  105. package/packages/piagent-core/subagents/piagent-scout.md +37 -0
  106. package/packages/piagent-core/subagents/piagent-worker.md +44 -0
  107. package/packs/engineering-base/pack.json +123 -0
  108. package/packs/engineering-base/recipes/bounded-change.json +82 -0
  109. package/packs/web-delivery/pack.json +72 -0
  110. package/packs/web-delivery/recipes/verified-web-change.json +57 -0
  111. package/schemas/action-proposal.schema.json +90 -0
  112. package/schemas/capability-pack.schema.json +190 -0
  113. package/schemas/capability-recipe.schema.json +72 -0
  114. package/schemas/context-index.schema.json +258 -0
  115. package/schemas/eval-scenario.schema.json +67 -0
  116. package/schemas/project-profile.schema.json +555 -0
  117. package/schemas/task-contract.schema.json +314 -0
  118. package/scripts/audit-runtime-host.sh +78 -0
  119. package/scripts/bootstrap-local.sh +25 -0
  120. package/scripts/capability-catalog.mjs +290 -0
  121. package/scripts/check-runtime-advisories.mjs +114 -0
  122. package/scripts/configure-mcp.sh +301 -0
  123. package/scripts/configure-model-scope.sh +143 -0
  124. package/scripts/configure-subagents.sh +241 -0
  125. package/scripts/import-agent-instructions.mjs +199 -0
  126. package/scripts/init-project.sh +369 -0
  127. package/scripts/install-global.sh +532 -0
  128. package/scripts/link-project.sh +25 -0
  129. package/scripts/migrate-project-state.mjs +176 -0
  130. package/scripts/pi-auto.sh +79 -0
  131. package/scripts/pi-model-catalog.sh +154 -0
  132. package/scripts/pi-session-stats.sh +135 -0
  133. package/scripts/piagent-cli.mjs +53 -0
  134. package/scripts/profile-doctor.sh +238 -0
  135. package/scripts/quality-benchmark.sh +185 -0
  136. package/scripts/redaction-benchmark.mjs +227 -0
  137. package/scripts/runtime-policy-smoke.sh +48 -0
  138. package/scripts/setup.sh +425 -0
  139. package/scripts/team-doctor.sh +461 -0
  140. package/scripts/verify-local.sh +540 -0
  141. package/scripts/verify-release-identity.mjs +85 -0
  142. package/scripts/verify-vercel-link.mjs +64 -0
  143. package/templates/global/mcp.json +9 -0
  144. package/templates/global/settings.json +37 -0
  145. package/templates/project/.mcp.json +9 -0
  146. package/templates/project/.pi/context-index.json +25 -0
  147. package/templates/project/.pi/gitignore.template +22 -0
  148. package/templates/project/.pi/mcp.json +9 -0
  149. package/templates/project/.pi/memory/MEMORY.md +11 -0
  150. package/templates/project/.pi/memory/memory_summary.md +9 -0
  151. package/templates/project/.pi/piagent-profile.json +107 -0
  152. package/templates/project/.pi/project-context.md +30 -0
  153. package/templates/project/.pi/settings.json +17 -0
  154. package/templates/project/.pi/task-contract.template.json +74 -0
  155. package/templates/project/.pi/tech-context/README.md +7 -0
  156. package/templates/project/.pi/tech-stack.json +10 -0
  157. package/templates/project/AGENTS.md +34 -0
  158. package/templates/project/REVIEW_GUIDELINES.md +23 -0
  159. package/types/pi-runtime-shims.d.ts +13 -0
@@ -0,0 +1,540 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ OFFLINE=false
6
+
7
+ usage() {
8
+ cat <<'USAGE'
9
+ Usage:
10
+ scripts/verify-local.sh [--offline]
11
+
12
+ Options:
13
+ --offline Skip checks that require a local Pi login/model catalog.
14
+ USAGE
15
+ }
16
+
17
+ while [[ $# -gt 0 ]]; do
18
+ case "$1" in
19
+ --offline)
20
+ OFFLINE=true
21
+ shift
22
+ ;;
23
+ -h|--help)
24
+ usage
25
+ exit 0
26
+ ;;
27
+ *)
28
+ echo "Unknown argument: $1" >&2
29
+ usage >&2
30
+ exit 2
31
+ ;;
32
+ esac
33
+ done
34
+
35
+ required_files=(
36
+ "$ROOT/README.md"
37
+ "$ROOT/SECURITY.md"
38
+ "$ROOT/AGENTS.md"
39
+ "$ROOT/CHANGELOG.md"
40
+ "$ROOT/.npmignore"
41
+ "$ROOT/package.json"
42
+ "$ROOT/package-lock.json"
43
+ "$ROOT/tsconfig.json"
44
+ "$ROOT/.github/workflows/verify.yml"
45
+ "$ROOT/.github/workflows/codeql.yml"
46
+ "$ROOT/.github/dependabot.yml"
47
+ "$ROOT/types/pi-runtime-shims.d.ts"
48
+ "$ROOT/.pi/settings.json"
49
+ "$ROOT/.pi/piagent-profile.json"
50
+ "$ROOT/.pi/piagent-profile.lock.json"
51
+ "$ROOT/.pi/project-context.md"
52
+ "$ROOT/packages/piagent-core/package.json"
53
+ "$ROOT/packages/piagent-core/extensions/piagent-guard.ts"
54
+ "$ROOT/packages/piagent-core/extensions/policy-core.js"
55
+ "$ROOT/packages/piagent-core/extensions/redaction-core.js"
56
+ "$ROOT/packages/piagent-core/extensions/runtime-evidence.js"
57
+ "$ROOT/packages/piagent-core/security/sensitive-data.js"
58
+ "$ROOT/packages/piagent-core/capabilities/capability-core.js"
59
+ "$ROOT/packages/piagent-core/prompts/onboard-project.md"
60
+ "$ROOT/packages/piagent-core/prompts/piagent-commands.md"
61
+ "$ROOT/packages/piagent-core/prompts/model-options.md"
62
+ "$ROOT/packages/piagent-core/prompts/memory-policy.md"
63
+ "$ROOT/packages/piagent-core/prompts/platform-improve.md"
64
+ "$ROOT/packages/piagent-core/prompts/be-to-fe.md"
65
+ "$ROOT/packages/piagent-core/prompts/scout.md"
66
+ "$ROOT/packages/piagent-core/prompts/task.md"
67
+ "$ROOT/packages/piagent-core/prompts/commit.md"
68
+ "$ROOT/packages/piagent-core/prompts/pr.md"
69
+ "$ROOT/packages/piagent-core/prompts/discuss.md"
70
+ "$ROOT/packages/piagent-core/prompts/plan.md"
71
+ "$ROOT/packages/piagent-core/prompts/review.md"
72
+ "$ROOT/packages/piagent-core/skills/piagent-ops/SKILL.md"
73
+ "$ROOT/packages/piagent-core/skills/piagent-source-cache/SKILL.md"
74
+ "$ROOT/packages/piagent-core/skills/piagent-source-cache/checkout-source-repo.sh"
75
+ "$ROOT/packages/piagent-core/subagents/piagent-scout.md"
76
+ "$ROOT/packages/piagent-core/subagents/piagent-planner.md"
77
+ "$ROOT/packages/piagent-core/subagents/piagent-worker.md"
78
+ "$ROOT/packages/piagent-core/subagents/piagent-reviewer.md"
79
+ "$ROOT/packages/piagent-core/subagents/piagent-oracle.md"
80
+ "$ROOT/adapters/generic/profile.json"
81
+ "$ROOT/adapters/backend-api/profile.json"
82
+ "$ROOT/adapters/be-readonly-fe/profile.json"
83
+ "$ROOT/adapters/data/profile.json"
84
+ "$ROOT/adapters/devops/profile.json"
85
+ "$ROOT/adapters/docs/profile.json"
86
+ "$ROOT/adapters/fullstack/profile.json"
87
+ "$ROOT/adapters/mobile/profile.json"
88
+ "$ROOT/adapters/node-typescript/profile.json"
89
+ "$ROOT/adapters/python/profile.json"
90
+ "$ROOT/adapters/web-frontend/profile.json"
91
+ "$ROOT/templates/project/.pi/settings.json"
92
+ "$ROOT/templates/project/.pi/piagent-profile.json"
93
+ "$ROOT/templates/project/.mcp.json"
94
+ "$ROOT/templates/project/.pi/mcp.json"
95
+ "$ROOT/templates/project/.pi/project-context.md"
96
+ "$ROOT/templates/project/.pi/context-index.json"
97
+ "$ROOT/templates/project/.pi/tech-stack.json"
98
+ "$ROOT/templates/project/.pi/tech-context/README.md"
99
+ "$ROOT/templates/project/.pi/.npmignore"
100
+ "$ROOT/templates/project/.pi/memory/memory_summary.md"
101
+ "$ROOT/templates/project/.pi/memory/MEMORY.md"
102
+ "$ROOT/templates/project/.pi/.gitignore"
103
+ "$ROOT/templates/project/.pi/gitignore.template"
104
+ "$ROOT/templates/project/REVIEW_GUIDELINES.md"
105
+ "$ROOT/docs/quickstart-vietnamese.md"
106
+ "$ROOT/docs/command-reference-vietnamese.md"
107
+ "$ROOT/docs/auto-delegation-policy.md"
108
+ "$ROOT/docs/subagent-orchestration-capabilities.md"
109
+ "$ROOT/docs/project-onboarding.md"
110
+ "$ROOT/docs/workflow-recipes.md"
111
+ "$ROOT/docs/memory-policy.md"
112
+ "$ROOT/docs/model-options.md"
113
+ "$ROOT/docs/oauth-providers.md"
114
+ "$ROOT/docs/subagents-and-multiagent.md"
115
+ "$ROOT/docs/distribution-standard.md"
116
+ "$ROOT/docs/release-install-policy.md"
117
+ "$ROOT/docs/security-threat-model.md"
118
+ "$ROOT/docs/vercel-docs-site.md"
119
+ "$ROOT/docs/publishing-for-teams.md"
120
+ "$ROOT/docs/herdr-workflow.md"
121
+ "$ROOT/docs/runtime-harness-standard.md"
122
+ "$ROOT/docs/task-implementation-contract.md"
123
+ "$ROOT/docs/runtime-quality-baseline.md"
124
+ "$ROOT/docs/quality-benchmark.md"
125
+ "$ROOT/docs/package-architecture-notes.md"
126
+ "$ROOT/docs/capability-packs.md"
127
+ "$ROOT/docs/runtime-policy-design.md"
128
+ "$ROOT/docs-site/index.html"
129
+ "$ROOT/docs-site/favicon.svg"
130
+ "$ROOT/docs-site/assets/piagent-logo.svg"
131
+ "$ROOT/docs-site/vercel.json"
132
+ "$ROOT/schemas/project-profile.schema.json"
133
+ "$ROOT/schemas/task-contract.schema.json"
134
+ "$ROOT/schemas/capability-pack.schema.json"
135
+ "$ROOT/schemas/capability-recipe.schema.json"
136
+ "$ROOT/schemas/eval-scenario.schema.json"
137
+ "$ROOT/schemas/action-proposal.schema.json"
138
+ "$ROOT/packs/engineering-base/pack.json"
139
+ "$ROOT/packs/engineering-base/recipes/bounded-change.json"
140
+ "$ROOT/packs/web-delivery/pack.json"
141
+ "$ROOT/packs/web-delivery/recipes/verified-web-change.json"
142
+ "$ROOT/evals/scenarios/capability-resolution.json"
143
+ "$ROOT/catalog/capabilities.json"
144
+ "$ROOT/templates/project/.pi/task-contract.template.json"
145
+ "$ROOT/scripts/install-global.sh"
146
+ "$ROOT/scripts/audit-runtime-host.sh"
147
+ "$ROOT/scripts/verify-release-identity.mjs"
148
+ "$ROOT/scripts/verify-vercel-link.mjs"
149
+ "$ROOT/scripts/piagent-cli.mjs"
150
+ "$ROOT/scripts/init-project.sh"
151
+ "$ROOT/scripts/setup.sh"
152
+ "$ROOT/scripts/team-doctor.sh"
153
+ "$ROOT/scripts/link-project.sh"
154
+ "$ROOT/scripts/profile-doctor.sh"
155
+ "$ROOT/scripts/quality-benchmark.sh"
156
+ "$ROOT/scripts/runtime-policy-smoke.sh"
157
+ "$ROOT/scripts/pi-session-stats.sh"
158
+ "$ROOT/scripts/pi-auto.sh"
159
+ "$ROOT/scripts/pi-model-catalog.sh"
160
+ "$ROOT/scripts/configure-model-scope.sh"
161
+ "$ROOT/scripts/configure-mcp.sh"
162
+ "$ROOT/scripts/configure-subagents.sh"
163
+ "$ROOT/scripts/capability-catalog.mjs"
164
+ "$ROOT/scripts/migrate-project-state.mjs"
165
+ "$ROOT/scripts/import-agent-instructions.mjs"
166
+ "$ROOT/tests/capability-core.test.mjs"
167
+ "$ROOT/tests/piagent-guard-integration.test.mjs"
168
+ "$ROOT/tests/install-global.test.mjs"
169
+ "$ROOT/tests/package-distribution.test.mjs"
170
+ "$ROOT/tests/release-identity.test.mjs"
171
+ "$ROOT/tests/policy-core.test.mjs"
172
+ "$ROOT/tests/redaction-core.test.mjs"
173
+ "$ROOT/tests/runtime-evidence.test.mjs"
174
+ "$ROOT/tests/golden-enforcement.test.mjs"
175
+ "$ROOT/tests/capability-sources.test.mjs"
176
+ "$ROOT/packages/piagent-core/capabilities/capability-sources.js"
177
+ "$ROOT/packages/piagent-core/extensions/guard-shell-analysis.ts"
178
+ "$ROOT/tests/guard-shell-analysis.test.mjs"
179
+ "$ROOT/tests/runtime-advisories.test.mjs"
180
+ "$ROOT/scripts/check-runtime-advisories.mjs"
181
+ "$ROOT/tests/migrate-project-state.test.mjs"
182
+ "$ROOT/tests/import-agent-instructions.test.mjs"
183
+ "$ROOT/evals/golden/enforcement-decisions.json"
184
+ )
185
+
186
+ for file in "${required_files[@]}"; do
187
+ if [[ ! -s "$file" ]]; then
188
+ echo "Missing required file: $file"
189
+ exit 1
190
+ fi
191
+ done
192
+
193
+ node --input-type=module - "$ROOT" <<'NODE'
194
+ import fs from "node:fs";
195
+ import path from "node:path";
196
+
197
+ const root = process.argv[2];
198
+ const jsonFiles = [
199
+ "package.json",
200
+ ".mcp.json",
201
+ ".pi/settings.json",
202
+ ".pi/piagent-profile.json",
203
+ ".pi/piagent-profile.lock.json",
204
+ "packages/piagent-core/package.json",
205
+ "packages/piagent-core/policies/base-policy.json",
206
+ "adapters/generic/profile.json",
207
+ "adapters/backend-api/profile.json",
208
+ "adapters/be-readonly-fe/profile.json",
209
+ "adapters/data/profile.json",
210
+ "adapters/devops/profile.json",
211
+ "adapters/docs/profile.json",
212
+ "adapters/fullstack/profile.json",
213
+ "adapters/mobile/profile.json",
214
+ "adapters/node-typescript/profile.json",
215
+ "adapters/python/profile.json",
216
+ "adapters/web-frontend/profile.json",
217
+ "templates/project/.pi/settings.json",
218
+ "templates/project/.pi/piagent-profile.json",
219
+ "templates/project/.mcp.json",
220
+ "templates/project/.pi/task-contract.template.json",
221
+ "templates/project/.pi/mcp.json",
222
+ "templates/global/settings.json",
223
+ "templates/global/mcp.json",
224
+ "schemas/project-profile.schema.json",
225
+ "schemas/task-contract.schema.json",
226
+ "schemas/capability-pack.schema.json",
227
+ "schemas/capability-recipe.schema.json",
228
+ "schemas/eval-scenario.schema.json",
229
+ "schemas/action-proposal.schema.json",
230
+ "packs/engineering-base/pack.json",
231
+ "packs/engineering-base/recipes/bounded-change.json",
232
+ "packs/web-delivery/pack.json",
233
+ "packs/web-delivery/recipes/verified-web-change.json",
234
+ "evals/scenarios/capability-resolution.json",
235
+ "catalog/capabilities.json"
236
+ ];
237
+
238
+ for (const rel of jsonFiles) {
239
+ const target = path.join(root, rel);
240
+ JSON.parse(fs.readFileSync(target, "utf8"));
241
+ }
242
+
243
+ const rootPkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
244
+ if (!rootPkg.pi || !rootPkg.pi.extensions || !rootPkg.pi.prompts || !rootPkg.pi.skills) {
245
+ throw new Error("root package.json missing pi manifest");
246
+ }
247
+ if (!rootPkg.pi.subagents?.agents?.length) {
248
+ throw new Error("root package.json missing pi.subagents.agents");
249
+ }
250
+ const expectedPeers = {
251
+ "@earendil-works/pi-ai": "0.81.1",
252
+ "@earendil-works/pi-coding-agent": "0.81.1",
253
+ typebox: "1.1.38"
254
+ };
255
+ for (const [name, version] of Object.entries(expectedPeers)) {
256
+ if (rootPkg.peerDependencies?.[name] !== version) throw new Error(`root package peer ${name} must be pinned to ${version}`);
257
+ if (rootPkg.peerDependenciesMeta?.[name]?.optional !== true) throw new Error(`root package peer ${name} must remain optional`);
258
+ }
259
+
260
+ const pkg = JSON.parse(fs.readFileSync(path.join(root, "packages/piagent-core/package.json"), "utf8"));
261
+ if (!pkg.pi || !pkg.pi.extensions || !pkg.pi.prompts || !pkg.pi.skills) {
262
+ throw new Error("packages/piagent-core/package.json missing pi manifest");
263
+ }
264
+ if (!pkg.pi.subagents?.agents?.length) {
265
+ throw new Error("packages/piagent-core/package.json missing pi.subagents.agents");
266
+ }
267
+ NODE
268
+
269
+ grep -R "auth.json" "$ROOT/docs" "$ROOT/packages/piagent-core" "$ROOT/templates" >/dev/null
270
+ grep -R "piagent_context" "$ROOT/packages/piagent-core" >/dev/null
271
+ grep -R "piagent_permission_status" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/README.md" >/dev/null
272
+ grep -R "/full-access" "$ROOT/docs" "$ROOT/README.md" "$ROOT/packages/piagent-core/README.md" >/dev/null
273
+ grep -R "piagent_exec_policy_check" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
274
+ grep -R "piagent_context_budget" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
275
+ grep -R "piagent_tool_policy_check" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
276
+ grep -R "piagent_task_gate_check" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
277
+ grep -R "piagent_usage_snapshot" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
278
+ grep -R "/piagent-usage" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/README.md" >/dev/null
279
+ grep -R "/piagent-commands" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
280
+ grep -R "auto-delegation" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" "$ROOT/templates/project/AGENTS.md" >/dev/null
281
+ grep -R "Subagents used/not used" "$ROOT/packages/piagent-core/prompts" "$ROOT/docs/auto-delegation-policy.md" >/dev/null
282
+ grep -R "Subagent orchestration capabilities" "$ROOT/README.md" "$ROOT/docs/subagent-orchestration-capabilities.md" >/dev/null
283
+ grep -R "pi-web-access" "$ROOT/README.md" "$ROOT/docs" "$ROOT/scripts/install-global.sh" "$ROOT/scripts/setup.sh" >/dev/null
284
+ grep -F 'PI_MCP_ADAPTER_SOURCE="npm:pi-mcp-adapter@2.11.0"' "$ROOT/scripts/install-global.sh" >/dev/null
285
+ grep -F 'PI_SUBAGENTS_SOURCE="npm:pi-subagents@0.35.1"' "$ROOT/scripts/install-global.sh" >/dev/null
286
+ grep -F 'PI_WEB_ACCESS_SOURCE="npm:pi-web-access@0.13.0"' "$ROOT/scripts/install-global.sh" >/dev/null
287
+ grep -F 'PI_MCP_ADAPTER_VERSION="2.11.0"' "$ROOT/scripts/audit-runtime-host.sh" >/dev/null
288
+ grep -F 'PI_SUBAGENTS_VERSION="0.35.1"' "$ROOT/scripts/audit-runtime-host.sh" >/dev/null
289
+ grep -F 'PI_WEB_ACCESS_VERSION="0.13.0"' "$ROOT/scripts/audit-runtime-host.sh" >/dev/null
290
+ node --input-type=module - "$ROOT/scripts/install-global.sh" "$ROOT/scripts/audit-runtime-host.sh" <<'NODE'
291
+ import fs from "node:fs";
292
+
293
+ const installer = fs.readFileSync(process.argv[2], "utf8");
294
+ const audit = fs.readFileSync(process.argv[3], "utf8");
295
+ const pins = [
296
+ ["PI_MCP_ADAPTER_SOURCE", "PI_MCP_ADAPTER_VERSION", "pi-mcp-adapter"],
297
+ ["PI_SUBAGENTS_SOURCE", "PI_SUBAGENTS_VERSION", "pi-subagents"],
298
+ ["PI_WEB_ACCESS_SOURCE", "PI_WEB_ACCESS_VERSION", "pi-web-access"]
299
+ ];
300
+ for (const [sourceName, versionName, packageName] of pins) {
301
+ const source = installer.match(new RegExp(`^${sourceName}="npm:${packageName}@([^"]+)"$`, "m"))?.[1];
302
+ const audited = audit.match(new RegExp(`^${versionName}="([^"]+)"$`, "m"))?.[1];
303
+ if (!source || !audited || source !== audited) {
304
+ throw new Error(`${packageName} installer pin (${source ?? "missing"}) does not match runtime audit pin (${audited ?? "missing"})`);
305
+ }
306
+ }
307
+ NODE
308
+ grep -F 'actions/checkout@11d5960a326750d5838078e36cf38b85af677262' "$ROOT/.github/workflows/verify.yml" "$ROOT/.github/workflows/codeql.yml" >/dev/null
309
+ grep -F 'actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020' "$ROOT/.github/workflows/verify.yml" >/dev/null
310
+ grep -F 'github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81' "$ROOT/.github/workflows/codeql.yml" >/dev/null
311
+ grep -F 'github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81' "$ROOT/.github/workflows/codeql.yml" >/dev/null
312
+ grep -F 'git cat-file -t "refs/tags/$RELEASE_TAG"' "$ROOT/.github/workflows/verify.yml" >/dev/null
313
+ if grep -R -E '^[[:space:]]*uses:[[:space:]]+[^@[:space:]]+@(main|master|v[0-9]+([.][0-9]+)*)[[:space:]]*(#.*)?$' "$ROOT/.github/workflows" >/dev/null; then
314
+ echo "GitHub Actions workflow contains a mutable action reference" >&2
315
+ exit 1
316
+ fi
317
+ # A single-line `run:` whose value contains ": " ends the plain scalar early and
318
+ # makes the whole workflow unparseable. GitHub reports that as an instant
319
+ # failure with no job, so the gate stops running while still looking present.
320
+ # Use a block scalar or quote the value.
321
+ if grep -R -n -E '^[[:space:]]*run:[[:space:]]+[^|>"'"'"'].*:[[:space:]]' "$ROOT/.github/workflows" >/dev/null; then
322
+ echo "GitHub Actions workflow has an unquoted run: value containing a colon-space; use a block scalar" >&2
323
+ grep -R -n -E '^[[:space:]]*run:[[:space:]]+[^|>"'"'"'].*:[[:space:]]' "$ROOT/.github/workflows" >&2
324
+ exit 1
325
+ fi
326
+ grep -F 'p.peerDependencies?.["@earendil-works/pi-coding-agent"]' "$ROOT/scripts/setup.sh" >/dev/null
327
+ grep -F 'run_cmd npm install -g --ignore-scripts "@earendil-works/pi-coding-agent@$expected_pi_version"' "$ROOT/scripts/setup.sh" >/dev/null
328
+ grep -F 'validate-source --package-source "$PACKAGE_SOURCE"' "$ROOT/scripts/install-global.sh" >/dev/null
329
+ grep -F 'verify_npm_integrity "$PI_MCP_ADAPTER_SOURCE" "$PI_MCP_ADAPTER_INTEGRITY"' "$ROOT/scripts/install-global.sh" >/dev/null
330
+ grep -F 'verify_npm_integrity "$PI_SUBAGENTS_SOURCE" "$PI_SUBAGENTS_INTEGRITY"' "$ROOT/scripts/install-global.sh" >/dev/null
331
+ grep -F 'verify_npm_integrity "$PI_WEB_ACCESS_SOURCE" "$PI_WEB_ACCESS_INTEGRITY"' "$ROOT/scripts/install-global.sh" >/dev/null
332
+ grep -R "parallel-review" "$ROOT/docs" "$ROOT/README.md" >/dev/null
333
+ grep -R "intercomBridge" "$ROOT/scripts/configure-subagents.sh" "$ROOT/docs/subagents-and-multiagent.md" >/dev/null
334
+ grep -R "waitTool" "$ROOT/scripts/configure-subagents.sh" "$ROOT/docs/subagents-and-multiagent.md" >/dev/null
335
+ grep -R "piagent_profile_options" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
336
+ grep -R "piagent_profile_apply" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
337
+ grep -R "/profile auto" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core" >/dev/null
338
+ grep -R "piagent_profile_tech_context_record" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/README.md" >/dev/null
339
+ grep -R "/profile tech" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
340
+ grep -R "/commit" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
341
+ grep -R "/pr" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
342
+ grep -R "piagent_project_onboarding_record" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
343
+ grep -R "piagent_memory_status" "$ROOT/packages/piagent-core" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
344
+ grep -R "piagent_memory_note" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
345
+ grep -R "piagent_memory_search" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
346
+ grep -R "piagent_memory_citation_record" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
347
+ grep -R "piagent_context_index_status" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
348
+ grep -R "piagent_context_index_record" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
349
+ grep -R "piagent_context_index_search" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
350
+ grep -R "/context-index" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
351
+ grep -R "/onboard-project" "$ROOT/README.md" "$ROOT/docs" "$ROOT/templates/project/AGENTS.md" >/dev/null
352
+ grep -R "/memory-policy" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
353
+ grep -R "/model-options" "$ROOT/README.md" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
354
+ grep -R "anthropic/claude" "$ROOT/README.md" "$ROOT/docs/model-options.md" "$ROOT/packages/piagent-core/prompts/model-options.md" >/dev/null
355
+ grep -R "gpt-5.6" "$ROOT/README.md" "$ROOT/docs/model-options.md" "$ROOT/packages/piagent-core/prompts/model-options.md" >/dev/null
356
+ grep -R "claude-fable-5" "$ROOT/README.md" "$ROOT/docs/model-options.md" "$ROOT/packages/piagent-core/prompts/model-options.md" >/dev/null
357
+ grep -R "piagent-models" "$ROOT/README.md" "$ROOT/docs/model-options.md" >/dev/null
358
+ grep -R "enabledModels" "$ROOT/templates/global/settings.json" "$ROOT/docs/model-options.md" "$ROOT/scripts/configure-model-scope.sh" >/dev/null
359
+ grep -R "piagent-mcp" "$ROOT/README.md" "$ROOT/docs/mcp-and-tools.md" "$ROOT/scripts/configure-mcp.sh" >/dev/null
360
+ grep -R "pi-mcp-adapter" "$ROOT/README.md" "$ROOT/docs/mcp-and-tools.md" "$ROOT/scripts/install-global.sh" >/dev/null
361
+ grep -R "piagent-subagents" "$ROOT/README.md" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/scripts/configure-subagents.sh" >/dev/null
362
+ grep -R "subagents-fleet" "$ROOT/docs/command-reference-vietnamese.md" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/README.md" >/dev/null
363
+ grep -R "health check" "$ROOT/docs/command-reference-vietnamese.md" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/README.md" >/dev/null
364
+ grep -R "pi-subagents" "$ROOT/README.md" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/scripts/install-global.sh" "$ROOT/scripts/setup.sh" >/dev/null
365
+ grep -R "piagent-scout" "$ROOT/README.md" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/packages/piagent-core/subagents" >/dev/null
366
+ grep -F "@upstash/context7-mcp@3.2.4" "$ROOT/scripts/configure-mcp.sh" >/dev/null
367
+ grep -F "@upstash/context7-mcp@3.2.4" "$ROOT/docs/mcp-and-tools.md" >/dev/null
368
+ grep -F "chrome-devtools-mcp@1.6.0" "$ROOT/scripts/configure-mcp.sh" >/dev/null
369
+ grep -F "chrome-devtools-mcp@1.6.0" "$ROOT/docs/mcp-and-tools.md" >/dev/null
370
+ grep -F "@playwright/mcp@0.0.78" "$ROOT/scripts/configure-mcp.sh" >/dev/null
371
+ grep -F "@playwright/mcp@0.0.78" "$ROOT/docs/mcp-and-tools.md" >/dev/null
372
+ grep -R "https://mcp.figma.com/mcp" "$ROOT/scripts/configure-mcp.sh" "$ROOT/docs/mcp-and-tools.md" >/dev/null
373
+ grep -F "ghcr.io/github/github-mcp-server@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3" "$ROOT/scripts/configure-mcp.sh" >/dev/null
374
+ grep -F "ghcr.io/github/github-mcp-server@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3" "$ROOT/docs/mcp-and-tools.md" >/dev/null
375
+ grep -F '"GITHUB_READ_ONLY=1"' "$ROOT/scripts/configure-mcp.sh" >/dev/null
376
+ grep -F '"GITHUB_READ_ONLY=1"' "$ROOT/docs/mcp-and-tools.md" >/dev/null
377
+ grep -F '"GITHUB_LOCKDOWN_MODE=1"' "$ROOT/scripts/configure-mcp.sh" >/dev/null
378
+ grep -F '"GITHUB_LOCKDOWN_MODE=1"' "$ROOT/docs/mcp-and-tools.md" >/dev/null
379
+ grep -F 'CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS: "1"' "$ROOT/scripts/configure-mcp.sh" >/dev/null
380
+ grep -F '"CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS": "1"' "$ROOT/docs/mcp-and-tools.md" >/dev/null
381
+ grep -F 'CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS: "1"' "$ROOT/scripts/configure-mcp.sh" >/dev/null
382
+ grep -F '"CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS": "1"' "$ROOT/docs/mcp-and-tools.md" >/dev/null
383
+ grep -F 'configure-mcp.sh" --scope global --preset "$MCP_PRESET" --replace' "$ROOT/scripts/install-global.sh" >/dev/null
384
+ grep -F 'piagent-mcp --preset core --scope global --replace' "$ROOT/scripts/configure-mcp.sh" >/dev/null
385
+ if grep -E '@latest|"@upstash/context7-mcp"|"chrome-devtools-mcp"|"@playwright/mcp"|"ghcr\.io/github/github-mcp-server"' "$ROOT/scripts/configure-mcp.sh" >/dev/null; then
386
+ echo "MCP production presets contain a mutable dependency source"
387
+ exit 1
388
+ fi
389
+ grep -R "Ctrl+L" "$ROOT/README.md" "$ROOT/docs/model-options.md" "$ROOT/docs/team-onboarding.md" "$ROOT/docs/quickstart-vietnamese.md" >/dev/null
390
+ grep -R "/platform-improve" "$ROOT/packages/piagent-core/prompts" "$ROOT/docs" >/dev/null
391
+ grep -R "/be-to-fe" "$ROOT/packages/piagent-core/prompts" "$ROOT/docs" >/dev/null
392
+ grep -R "/scout" "$ROOT/packages/piagent-core/prompts" "$ROOT/docs" "$ROOT/README.md" >/dev/null
393
+ grep -R "piagent_context_preflight" "$ROOT/packages/piagent-core" "$ROOT/docs" >/dev/null
394
+ grep -R ".pi/task-inbox" "$ROOT/.gitignore" "$ROOT/templates/project/.pi/.gitignore" "$ROOT/docs" >/dev/null
395
+ grep -R "Task Implementation Contract" "$ROOT/docs" "$ROOT/packages/piagent-core/prompts" >/dev/null
396
+ grep -R "piagent-task-trace" "$ROOT/packages/piagent-core/extensions/piagent-guard.ts" "$ROOT/docs" >/dev/null
397
+ grep -R "piagent-source-cache" "$ROOT/packages/piagent-core/skills" "$ROOT/templates/project/AGENTS.md" >/dev/null
398
+ grep -R "piagent_source_checkout" "$ROOT/packages/piagent-core" >/dev/null
399
+ grep -R "scripts/setup.sh" "$ROOT/README.md" "$ROOT/docs" >/dev/null
400
+ grep -R "quality-benchmark.sh" "$ROOT/README.md" "$ROOT/docs" >/dev/null
401
+ grep -R "piagent-capabilities" "$ROOT/README.md" "$ROOT/docs/capability-packs.md" >/dev/null
402
+ grep -R ".pi-subagents/" "$ROOT/.gitignore" "$ROOT/docs/subagents-and-multiagent.md" "$ROOT/docs/distribution-standard.md" "$ROOT/scripts/init-project.sh" >/dev/null
403
+ test -s "$ROOT/tests/policy-core.test.mjs"
404
+
405
+ public_wording_pattern="$(
406
+ node --input-type=module <<'NODE'
407
+ const terms = [
408
+ ["platform-", "mig", "ration"].join(""),
409
+ ["codex-", "mig", "ration"].join(""),
410
+ ["codex-", "par", "ity"].join(""),
411
+ ["benchmark-", "par", "ity"].join(""),
412
+ ["harness-", "mig", "ration"].join(""),
413
+ ["agent-", "stuff"].join(""),
414
+ ["mit", "suhiko"].join(""),
415
+ ["Cod", "ex CLI"].join(""),
416
+ ["Claude", " CLI"].join(""),
417
+ ["Cod", "ex-inspired"].join(""),
418
+ ["Cod", "ex-grade"].join(""),
419
+ ["Pi vs ", "Codex"].join(""),
420
+ ["vs ", "Claude"].join(""),
421
+ ["reference ", "repo"].join(""),
422
+ ["repo ", "tham ", "khảo"].join(""),
423
+ ["nguồn ", "tham ", "khảo"].join(""),
424
+ ["tham ", "khảo"].join("")
425
+ ];
426
+ const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
427
+ console.log(terms.map(escapeRegex).join("|"));
428
+ NODE
429
+ )"
430
+
431
+ if grep -R -E -i \
432
+ "$public_wording_pattern" \
433
+ "$ROOT/README.md" \
434
+ "$ROOT/docs" \
435
+ "$ROOT/packages/piagent-core/README.md" \
436
+ "$ROOT/packages/piagent-core/prompts" \
437
+ "$ROOT/templates/project/AGENTS.md" >/dev/null; then
438
+ echo "Public docs contain non-neutral platform wording"
439
+ exit 1
440
+ fi
441
+
442
+ node --check "$ROOT/packages/piagent-core/extensions/piagent-guard.ts" >/dev/null
443
+ node --check "$ROOT/packages/piagent-core/extensions/policy-core.js" >/dev/null
444
+ node --check "$ROOT/packages/piagent-core/extensions/redaction-core.js" >/dev/null
445
+ node --check "$ROOT/packages/piagent-core/extensions/runtime-evidence.js" >/dev/null
446
+ node --check "$ROOT/packages/piagent-core/security/sensitive-data.js" >/dev/null
447
+ node --check "$ROOT/packages/piagent-core/capabilities/capability-core.js" >/dev/null
448
+ node --check "$ROOT/packages/piagent-core/capabilities/capability-sources.js" >/dev/null
449
+ node --check "$ROOT/scripts/capability-catalog.mjs" >/dev/null
450
+ node --check "$ROOT/scripts/piagent-cli.mjs" >/dev/null
451
+ node --check "$ROOT/scripts/migrate-project-state.mjs" >/dev/null
452
+ node --check "$ROOT/scripts/import-agent-instructions.mjs" >/dev/null
453
+ node --check "$ROOT/scripts/check-runtime-advisories.mjs" >/dev/null
454
+ (cd "$ROOT" && npm test) >/dev/null
455
+ if [[ -x "$ROOT/node_modules/.bin/tsc" ]]; then
456
+ (cd "$ROOT" && npm run typecheck) >/dev/null
457
+ fi
458
+ bash -n "$ROOT/scripts/quality-benchmark.sh"
459
+ bash -n "$ROOT/scripts/runtime-policy-smoke.sh"
460
+ bash -n "$ROOT/scripts/pi-session-stats.sh"
461
+ bash -n "$ROOT/scripts/pi-auto.sh"
462
+ bash -n "$ROOT/scripts/pi-model-catalog.sh"
463
+ bash -n "$ROOT/scripts/configure-model-scope.sh"
464
+ bash -n "$ROOT/scripts/configure-mcp.sh"
465
+ bash -n "$ROOT/scripts/configure-subagents.sh"
466
+ bash -n "$ROOT/scripts/install-global.sh"
467
+ bash -n "$ROOT/scripts/init-project.sh"
468
+ bash -n "$ROOT/scripts/setup.sh"
469
+ if [[ "$OFFLINE" == true || "${PIAGENT_VERIFY_OFFLINE:-}" == "1" || "${CI:-}" == "true" ]]; then
470
+ echo "WARN: skipping local Pi model catalog check in offline/CI mode" >&2
471
+ else
472
+ bash "$ROOT/scripts/pi-model-catalog.sh" --json >/dev/null
473
+ fi
474
+ bash "$ROOT/scripts/configure-model-scope.sh" --dry-run --preset full --default-model openai-codex/gpt-5.5:xhigh >/dev/null
475
+ bash "$ROOT/scripts/configure-mcp.sh" --list >/dev/null
476
+ bash "$ROOT/scripts/configure-mcp.sh" --dry-run --preset popular --scope project --project "$ROOT" >/dev/null
477
+ node --input-type=module - "$ROOT" <<'NODE'
478
+ import assert from "node:assert/strict";
479
+ import { execFileSync } from "node:child_process";
480
+ import fs from "node:fs";
481
+ import os from "node:os";
482
+ import path from "node:path";
483
+
484
+ const root = process.argv[2];
485
+ const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), "piagent-mcp-upgrade-"));
486
+ const configPath = path.join(fixtureRoot, "mcp.json");
487
+ try {
488
+ fs.writeFileSync(configPath, `${JSON.stringify({
489
+ mcpServers: {
490
+ context7: { command: "npx", args: ["-y", "@upstash/context7-mcp"] },
491
+ "chrome-devtools": { command: "npx", args: ["-y", "chrome-devtools-mcp@latest"] },
492
+ playwright: { command: "npx", args: ["-y", "@playwright/mcp@latest"] },
493
+ github: { command: "docker", args: ["run", "ghcr.io/github/github-mcp-server"] },
494
+ internal: { url: "https://mcp.example.invalid/api" }
495
+ }
496
+ }, null, 2)}\n`);
497
+ execFileSync("bash", [
498
+ path.join(root, "scripts", "configure-mcp.sh"),
499
+ "--config", configPath,
500
+ "--preset", "popular",
501
+ "--replace"
502
+ ], { stdio: "ignore" });
503
+ const upgraded = JSON.parse(fs.readFileSync(configPath, "utf8"));
504
+ assert.equal(upgraded.mcpServers.context7.args[1], "@upstash/context7-mcp@3.2.4");
505
+ assert.equal(upgraded.mcpServers["chrome-devtools"].args[1], "chrome-devtools-mcp@1.6.0");
506
+ assert.equal(upgraded.mcpServers["chrome-devtools"].env.CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS, "1");
507
+ assert.equal(upgraded.mcpServers["chrome-devtools"].env.CHROME_DEVTOOLS_MCP_NO_UPDATE_CHECKS, "1");
508
+ assert.equal(upgraded.mcpServers.playwright.args[1], "@playwright/mcp@0.0.78");
509
+ assert.ok(upgraded.mcpServers.github.args.includes("GITHUB_READ_ONLY=1"));
510
+ assert.ok(upgraded.mcpServers.github.args.includes("GITHUB_LOCKDOWN_MODE=1"));
511
+ assert.ok(upgraded.mcpServers.github.args.includes("ghcr.io/github/github-mcp-server@sha256:2b0c48b070f61e9d3969269ead600f62d00fb237b60ac849ef3d166ee7de9ad3"));
512
+ assert.deepEqual(upgraded.mcpServers.internal, { url: "https://mcp.example.invalid/api" });
513
+ } finally {
514
+ fs.rmSync(fixtureRoot, { recursive: true, force: true });
515
+ }
516
+ NODE
517
+ bash "$ROOT/scripts/configure-subagents.sh" --list >/dev/null
518
+ bash "$ROOT/scripts/configure-subagents.sh" --dry-run --preset safe >/dev/null
519
+ bash "$ROOT/scripts/runtime-policy-smoke.sh" >/dev/null
520
+
521
+ node "$ROOT/scripts/capability-catalog.mjs" catalog --check >/dev/null
522
+ node "$ROOT/scripts/capability-catalog.mjs" doctor --profile "$ROOT/.pi/piagent-profile.json" --lock "$ROOT/.pi/piagent-profile.lock.json" >/dev/null
523
+ node "$ROOT/scripts/capability-catalog.mjs" doctor --profile "$ROOT/adapters/generic/profile.json" >/dev/null
524
+ node "$ROOT/scripts/capability-catalog.mjs" doctor --profile "$ROOT/adapters/web-frontend/profile.json" >/dev/null
525
+
526
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/.pi/piagent-profile.json" >/dev/null
527
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/generic/profile.json" >/dev/null
528
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/backend-api/profile.json" >/dev/null
529
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/be-readonly-fe/profile.json" >/dev/null
530
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/data/profile.json" >/dev/null
531
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/devops/profile.json" >/dev/null
532
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/docs/profile.json" >/dev/null
533
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/fullstack/profile.json" >/dev/null
534
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/mobile/profile.json" >/dev/null
535
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/node-typescript/profile.json" >/dev/null
536
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/python/profile.json" >/dev/null
537
+ bash "$ROOT/scripts/profile-doctor.sh" "$ROOT" "$ROOT/adapters/web-frontend/profile.json" >/dev/null
538
+ bash "$ROOT/scripts/team-doctor.sh" "$ROOT" --strict-share >/dev/null
539
+
540
+ echo "PASS: piagent-platform scaffold is complete"
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { execFileSync } from "node:child_process";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
9
+
10
+ function fail(message) {
11
+ process.stderr.write(`FAIL: ${message}\n`);
12
+ process.exit(1);
13
+ }
14
+
15
+ function readJson(relative) {
16
+ try {
17
+ return JSON.parse(fs.readFileSync(path.join(root, relative), "utf8"));
18
+ } catch (error) {
19
+ fail(`${relative} is missing or invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
20
+ }
21
+ }
22
+
23
+ function parseArguments(values) {
24
+ const parsed = { tag: "", commit: "" };
25
+ for (let index = 0; index < values.length; index += 1) {
26
+ const option = values[index];
27
+ if (option === "-h" || option === "--help") {
28
+ process.stdout.write("Usage: node scripts/verify-release-identity.mjs [--tag vX.Y.Z --commit <40-char-sha>]\n");
29
+ process.exit(0);
30
+ }
31
+ if (option !== "--tag" && option !== "--commit") fail(`unknown option ${option}`);
32
+ const key = option.slice(2);
33
+ if (parsed[key]) fail(`duplicate option ${option}`);
34
+ const value = values[index + 1];
35
+ if (!value || value.startsWith("--")) fail(`${option} requires a value`);
36
+ parsed[key] = value;
37
+ index += 1;
38
+ }
39
+ if (Boolean(parsed.tag) !== Boolean(parsed.commit)) fail("--tag and --commit must be provided together");
40
+ return parsed;
41
+ }
42
+
43
+ const options = parseArguments(process.argv.slice(2));
44
+ const rootPackage = readJson("package.json");
45
+ const corePackage = readJson("packages/piagent-core/package.json");
46
+ const packageLock = readJson("package-lock.json");
47
+ const capabilityLock = readJson(".pi/piagent-profile.lock.json");
48
+ const version = rootPackage.version;
49
+ const expectedTag = `v${version}`;
50
+
51
+ // The package is published now, so the old private-forever rule is gone. What
52
+ // still has to hold is that a scoped package cannot reach the registry as
53
+ // restricted by accident, and cannot ship without provenance.
54
+ if (rootPackage.name !== "@piagent/platform") fail("root package must be named @piagent/platform");
55
+ if (rootPackage.private) fail("root package must not be private; publishing is intended");
56
+ if (rootPackage.publishConfig?.access !== "public") fail("scoped package must declare publishConfig.access=public");
57
+ if (rootPackage.publishConfig?.provenance !== true) fail("root package must publish with provenance");
58
+ if (rootPackage.repository?.url !== "https://github.com/Vt-mmm/piagent.git") fail("root package repository URL is not canonical");
59
+ if (rootPackage.dependencies && Object.keys(rootPackage.dependencies).length > 0) fail("root package has unexpected runtime dependencies");
60
+ if (packageLock.name !== rootPackage.name || packageLock.packages?.[""]?.name !== rootPackage.name) fail("package-lock root identity does not match package.json");
61
+ if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version ?? "")) fail("package.json version is not a supported release version");
62
+ if (corePackage.version !== version) fail("root and core package versions do not match");
63
+ if (packageLock.packages?.[""]?.version !== version) fail("package-lock root version does not match package.json");
64
+ if (packageLock.packages?.["packages/piagent-core"]?.version !== version) fail("package-lock core version does not match package.json");
65
+ if (capabilityLock.core?.packageVersion !== version) fail("capability lock packageVersion does not match package.json");
66
+
67
+ const changelog = fs.readFileSync(path.join(root, "CHANGELOG.md"), "utf8");
68
+ if (!changelog.includes(`## ${expectedTag} -`)) fail(`CHANGELOG.md has no ${expectedTag} release section`);
69
+
70
+ const docsSite = fs.readFileSync(path.join(root, "docs-site/index.html"), "utf8");
71
+ if (!docsSite.includes(`${expectedTag} docs`)) fail(`docs-site version badge does not identify ${expectedTag}`);
72
+
73
+ if (options.tag) {
74
+ if (options.tag !== expectedTag) fail(`release tag ${options.tag} does not match package version ${expectedTag}`);
75
+ if (!/^[0-9a-fA-F]{40}$/.test(options.commit)) fail("--commit must be a 40-character commit SHA");
76
+ let head;
77
+ try {
78
+ head = execFileSync("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
79
+ } catch (error) {
80
+ fail(`could not resolve the checked-out commit: ${error instanceof Error ? error.message : String(error)}`);
81
+ }
82
+ if (head.toLowerCase() !== options.commit.toLowerCase()) fail("checked-out commit does not match the release commit");
83
+ }
84
+
85
+ process.stdout.write(`PASS: release identity ${expectedTag}${options.commit ? ` @ ${options.commit.toLowerCase()}` : ""}\n`);