pi-harness-runtime 1.1.433 → 1.1.434

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 (111) hide show
  1. package/package.json +1 -1
  2. package/packages/a2a-adapter/package.json +1 -1
  3. package/packages/agent-policy/package.json +1 -1
  4. package/packages/architecture-generator/package.json +1 -1
  5. package/packages/auth/package.json +1 -1
  6. package/packages/autonomous-refactor/package.json +1 -1
  7. package/packages/autonomous-runtime/package.json +1 -1
  8. package/packages/cache-strategy/package.json +1 -1
  9. package/packages/capability-registry/package.json +1 -1
  10. package/packages/checkpoint/package.json +1 -1
  11. package/packages/cli-plugin-sdk/package.json +1 -1
  12. package/packages/clipboard/package.json +1 -1
  13. package/packages/clipboard-plugin/package.json +1 -1
  14. package/packages/code-generation/package.json +1 -1
  15. package/packages/code-review/package.json +1 -1
  16. package/packages/codex-adapter/package.json +1 -1
  17. package/packages/codex-watcher/package.json +1 -1
  18. package/packages/config-capture/package.json +1 -1
  19. package/packages/connection-runtime/package.json +1 -1
  20. package/packages/context-compiler/package.json +1 -1
  21. package/packages/context-discovery/package.json +1 -1
  22. package/packages/context-manager/package.json +1 -1
  23. package/packages/contracts/package.json +1 -1
  24. package/packages/cookie-sanitizer/package.json +1 -1
  25. package/packages/cost-optimizer/package.json +1 -1
  26. package/packages/dependency-analyzer/package.json +1 -1
  27. package/packages/django-plugin/package.json +1 -1
  28. package/packages/doc-generator/package.json +1 -1
  29. package/packages/durable-review/package.json +1 -1
  30. package/packages/e2e-tester/package.json +1 -1
  31. package/packages/evaluation-engine/package.json +1 -1
  32. package/packages/evaluation-runner/package.json +1 -1
  33. package/packages/event-bus/package.json +1 -1
  34. package/packages/event-sink/package.json +1 -1
  35. package/packages/event-store/package.json +1 -1
  36. package/packages/experience-replay/package.json +1 -1
  37. package/packages/feedback-collector/package.json +1 -1
  38. package/packages/file-copy-helper/package.json +1 -1
  39. package/packages/framework-detector/package.json +1 -1
  40. package/packages/framework-plugin-sdk/package.json +1 -1
  41. package/packages/frappe-plugin/package.json +1 -1
  42. package/packages/generic-web-plugin/package.json +1 -1
  43. package/packages/health-monitor/package.json +1 -1
  44. package/packages/intent-analyzer/package.json +1 -1
  45. package/packages/jev-judge/package.json +1 -1
  46. package/packages/knowledge-graph/package.json +1 -1
  47. package/packages/knowledge-retrieval/package.json +1 -1
  48. package/packages/laravel-plugin/package.json +1 -1
  49. package/packages/learning-engine/package.json +1 -1
  50. package/packages/logging/package.json +1 -1
  51. package/packages/mcp-adapter/package.json +1 -1
  52. package/packages/memory-engine/package.json +1 -1
  53. package/packages/milestone-manager/package.json +1 -1
  54. package/packages/model-registry/package.json +1 -1
  55. package/packages/nextjs-plugin/package.json +1 -1
  56. package/packages/notification/package.json +1 -1
  57. package/packages/observability/package.json +1 -1
  58. package/packages/okf-indexer/package.json +1 -1
  59. package/packages/paperclip-integration/package.json +1 -1
  60. package/packages/performance-optimizer/package.json +1 -1
  61. package/packages/permission-mode/package.json +1 -1
  62. package/packages/privilege-broker/package.json +1 -1
  63. package/packages/project-analyzer/package.json +1 -1
  64. package/packages/project-bootstrap/package.json +1 -1
  65. package/packages/projection-engine/package.json +1 -1
  66. package/packages/prompt-compiler/package.json +1 -1
  67. package/packages/prompt-versioning/package.json +1 -1
  68. package/packages/provider-adapter-sdk/package.json +1 -1
  69. package/packages/provider-router/package.json +1 -1
  70. package/packages/provider-selector/package.json +1 -1
  71. package/packages/providers/package.json +1 -1
  72. package/packages/qdrant-skills/package.json +1 -1
  73. package/packages/quota-manager/package.json +1 -1
  74. package/packages/rate-limiter/package.json +1 -1
  75. package/packages/react-vite-plugin/package.json +1 -1
  76. package/packages/relay/package.json +1 -1
  77. package/packages/release-manager/package.json +1 -1
  78. package/packages/requirement-compiler/package.json +1 -1
  79. package/packages/runtime/package.json +1 -1
  80. package/packages/scheduler/package.json +1 -1
  81. package/packages/scheduler-adapter/package.json +1 -1
  82. package/packages/session/package.json +1 -1
  83. package/packages/session-api/package.json +1 -1
  84. package/packages/session-export/package.json +1 -1
  85. package/packages/shared-context/package.json +1 -1
  86. package/packages/skill-mcp-client/package.json +1 -1
  87. package/packages/skill-registry/package.json +1 -1
  88. package/packages/skills/package.json +1 -1
  89. package/packages/sprint-planner/package.json +1 -1
  90. package/packages/subscription-engine/package.json +1 -1
  91. package/packages/task-compiler/package.json +1 -1
  92. package/packages/tencentdb-memory/package.json +1 -1
  93. package/packages/tencentdb-sync/package.json +1 -1
  94. package/packages/test-data-generator/package.json +1 -1
  95. package/packages/test-generator/package.json +1 -1
  96. package/packages/todo-bd-sync/package.json +1 -1
  97. package/packages/token-estimation/package.json +1 -1
  98. package/packages/token-optimizer/package.json +1 -1
  99. package/packages/tooling-preference/package.json +1 -1
  100. package/packages/trajectory/package.json +1 -1
  101. package/packages/tui/package.json +1 -1
  102. package/packages/two-phase-review/package.json +1 -1
  103. package/packages/types/package.json +1 -1
  104. package/packages/voice-api/package.json +1 -1
  105. package/packages/webmcp-tester/package.json +1 -1
  106. package/packages/wiki/package.json +1 -1
  107. package/packages/workflow-events/package.json +1 -1
  108. package/packages/workspace-scanner/package.json +1 -1
  109. package/packages/worktree/package.json +1 -1
  110. package/packages/write-review/package.json +1 -1
  111. package/scripts/npm-verify-removal.mjs +302 -0
@@ -0,0 +1,302 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Verify that an npm removal actually happened.
4
+ *
5
+ * The removal itself is irreversible, so the report that follows it has to
6
+ * be trustworthy. The obvious way to check - ask the registry for one
7
+ * version at a time and treat a non-zero exit as "the version is gone" -
8
+ * cannot tell "the version is gone" from "the registry did not answer".
9
+ * A network hiccup during the check therefore reads as a successful
10
+ * removal, and the operator is told the private content is gone while it
11
+ * is still published.
12
+ *
13
+ * This verifier separates the two.
14
+ *
15
+ * What it proves, for a version that should be gone:
16
+ *
17
+ * 1. The version is absent from the packument's version map. The
18
+ * packument keeps a `time` entry that still names a removed version,
19
+ * so the version map - not the whole document - is the criterion.
20
+ * 2. The tarball answers 404. The packument entry is the listing; the
21
+ * tarball is the content. Only the second one proves that the
22
+ * private content is no longer downloadable.
23
+ *
24
+ * What it proves, for a version that should remain:
25
+ *
26
+ * 1. The version is still in the version map.
27
+ *
28
+ * What it proves, for a dist-tag:
29
+ *
30
+ * 1. The tag still points at the version it pointed at before.
31
+ *
32
+ * Exit codes:
33
+ *
34
+ * 0 everything the spec asks for was proven.
35
+ * 1 the spec was not met: a version is still published, a version is
36
+ * missing, or a dist-tag moved.
37
+ * 2 the state could not be established. The registry was unreachable
38
+ * or answered something unexpected. This is NOT a pass, and it is
39
+ * deliberately not the same code as a failure, because "I could not
40
+ * check" and "the check failed" call for different responses.
41
+ *
42
+ * The check reads the registry without a credential. It therefore proves
43
+ * what an anonymous reader can see, which is exactly the exposure that
44
+ * matters here.
45
+ *
46
+ * Usage:
47
+ *
48
+ * node scripts/npm-verify-removal.mjs <package> <spec.json>
49
+ * node scripts/npm-verify-removal.mjs <package> --capture <spec.json> <version> [version ...]
50
+ *
51
+ * The capture form records the state that the check will later prove: the
52
+ * versions to remove, every other published version as one to keep, and
53
+ * the dist-tags as they are at that moment. Capturing before the removal
54
+ * is what makes the later check meaningful - a spec written by hand can
55
+ * describe a state that was never the real one.
56
+ *
57
+ * The spec is a JSON document:
58
+ *
59
+ * {
60
+ * "gone": ["1.1.390", "1.1.391"],
61
+ * "keep": ["1.1.425"],
62
+ * "tags": { "latest": "1.1.433" }
63
+ * }
64
+ *
65
+ * Every section is optional. The registry comes from
66
+ * npm_config_registry, so a test can point it at a local server.
67
+ */
68
+
69
+ import { readFile, writeFile } from "node:fs/promises";
70
+
71
+ const REGISTRY = (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
72
+
73
+ /**
74
+ * The number of tarball probes that run at once. Each probe is a HEAD
75
+ * against a different URL, so the limit is about the registry's patience
76
+ * rather than this process's memory.
77
+ */
78
+ const PROBE_CONCURRENCY = 6;
79
+
80
+ async function main() {
81
+ const args = process.argv.slice(2);
82
+ const packageName = args[0];
83
+ if (!packageName) {
84
+ process.stderr.write("usage: npm-verify-removal.mjs <package> <spec.json>\n");
85
+ process.stderr.write(" npm-verify-removal.mjs <package> --capture <spec.json> <version> [version ...]\n");
86
+ return 2;
87
+ }
88
+
89
+ // The capture form records the current state instead of checking it.
90
+ if (args[1] === "--capture") {
91
+ const [, , specPath, ...gone] = args;
92
+ if (!specPath || gone.length === 0) {
93
+ process.stderr.write("usage: npm-verify-removal.mjs <package> --capture <spec.json> <version> [version ...]\n");
94
+ return 2;
95
+ }
96
+ return capture(packageName, specPath, gone);
97
+ }
98
+
99
+ const specPath = args[1];
100
+ if (!specPath) {
101
+ process.stderr.write("usage: npm-verify-removal.mjs <package> <spec.json>\n");
102
+ return 2;
103
+ }
104
+
105
+ let spec;
106
+ try {
107
+ spec = JSON.parse(await readFile(specPath, "utf8"));
108
+ } catch (error) {
109
+ process.stderr.write(`could not read the spec: ${error.message}\n`);
110
+ return 2;
111
+ }
112
+
113
+ const gone = spec.gone ?? [];
114
+ const keep = spec.keep ?? [];
115
+ const tags = spec.tags ?? {};
116
+
117
+ // One request for the whole packument. Asking per version would be
118
+ // 31 requests for a 31-version removal, and the whole document is
119
+ // what every check below needs.
120
+ let packument;
121
+ try {
122
+ const response = await fetch(packumentUrl(packageName));
123
+ if (!response.ok) {
124
+ process.stdout.write(`could not verify: the registry answered ${response.status} for the packument\n`);
125
+ return 2;
126
+ }
127
+ packument = await response.json();
128
+ } catch (error) {
129
+ process.stdout.write(`could not verify: the registry could not be reached (${error.message})\n`);
130
+ return 2;
131
+ }
132
+
133
+ const published = new Set(Object.keys(packument.versions ?? {}));
134
+ const failures = [];
135
+
136
+ // The versions that should be gone.
137
+ const stillPublished = gone.filter((version) => published.has(version));
138
+ for (const version of stillPublished) {
139
+ failures.push(`still published: ${version}`);
140
+ }
141
+
142
+ // The versions that should remain.
143
+ const missing = keep.filter((version) => !published.has(version));
144
+ for (const version of missing) {
145
+ failures.push(`missing: ${version}`);
146
+ }
147
+
148
+ // The dist-tags, which must not have moved.
149
+ const currentTags = packument["dist-tags"] ?? {};
150
+ for (const [name, expected] of Object.entries(tags)) {
151
+ const actual = currentTags[name];
152
+ if (actual !== expected) {
153
+ failures.push(`dist-tag ${name} points at ${actual ?? "(unset)"}, expected ${expected}`);
154
+ }
155
+ }
156
+
157
+ // The tarballs. A removed version must not be downloadable.
158
+ const probes = await mapLimit(
159
+ gone.filter((version) => !published.has(version)),
160
+ PROBE_CONCURRENCY,
161
+ (version) => probeTarball(packageName, version),
162
+ );
163
+ let unknown = 0;
164
+ for (const [version, result] of probes) {
165
+ if (result === "gone") continue;
166
+ if (result === "alive") {
167
+ failures.push(`the tarball is still downloadable: ${version}`);
168
+ } else {
169
+ unknown++;
170
+ failures.push(`could not determine the tarball state: ${version}`);
171
+ }
172
+ }
173
+
174
+ // The report.
175
+ process.stdout.write(`package: ${packageName}\n`);
176
+ process.stdout.write(`registry: ${REGISTRY}\n`);
177
+ process.stdout.write(`published versions: ${published.size}\n`);
178
+ process.stdout.write(`expected gone: ${gone.length}, expected to remain: ${keep.length}\n`);
179
+ if (Object.keys(tags).length > 0) {
180
+ const shown = Object.entries(tags)
181
+ .map(([name, value]) => `${name}=${value}`)
182
+ .join(", ");
183
+ process.stdout.write(`dist-tags checked: ${shown}\n`);
184
+ }
185
+
186
+ if (unknown > 0) {
187
+ process.stdout.write(`could not verify: ${unknown} tarball probe(s) did not answer\n`);
188
+ return 2;
189
+ }
190
+ if (failures.length > 0) {
191
+ process.stdout.write("not verified:\n");
192
+ for (const failure of failures) process.stdout.write(` ${failure}\n`);
193
+ return 1;
194
+ }
195
+
196
+ process.stdout.write("verified:\n");
197
+ process.stdout.write(` every one of the ${gone.length} removed version(s) is absent and its tarball answers 404\n`);
198
+ process.stdout.write(` every one of the ${keep.length} retained version(s) is still published\n`);
199
+ if (Object.keys(tags).length > 0) process.stdout.write(" every dist-tag still points where it did\n");
200
+ return 0;
201
+ }
202
+
203
+ /**
204
+ * Record the state that a later check will prove.
205
+ *
206
+ * Every published version that is not on the removal list is recorded as
207
+ * one to keep, and the dist-tags are recorded as they are now. A spec
208
+ * that was written by hand can describe a state that was never the real
209
+ * one; a captured one cannot.
210
+ */
211
+ async function capture(packageName, specPath, gone) {
212
+ let packument;
213
+ try {
214
+ const response = await fetch(packumentUrl(packageName));
215
+ if (!response.ok) {
216
+ process.stdout.write(`could not capture: the registry answered ${response.status} for the packument\n`);
217
+ return 2;
218
+ }
219
+ packument = await response.json();
220
+ } catch (error) {
221
+ process.stdout.write(`could not capture: the registry could not be reached (${error.message})\n`);
222
+ return 2;
223
+ }
224
+
225
+ const published = Object.keys(packument.versions ?? {});
226
+ const removing = new Set(gone);
227
+ const keep = published.filter((version) => !removing.has(version));
228
+ const spec = {
229
+ gone: [...removing],
230
+ keep,
231
+ tags: packument["dist-tags"] ?? {},
232
+ };
233
+ await writeFile(specPath, `${JSON.stringify(spec, null, 2)}\n`);
234
+
235
+ process.stdout.write(`captured the registry state into ${specPath}\n`);
236
+ process.stdout.write(` to remove: ${spec.gone.length}\n`);
237
+ process.stdout.write(` to keep: ${spec.keep.length}\n`);
238
+ const shown = Object.entries(spec.tags)
239
+ .map(([name, value]) => `${name}=${value}`)
240
+ .join(", ");
241
+ if (shown) process.stdout.write(` dist-tags: ${shown}\n`);
242
+ return 0;
243
+ }
244
+
245
+ /**
246
+ * The packument URL. A scoped name is encoded so the registry reads it
247
+ * as one package rather than a path.
248
+ */
249
+ function packumentUrl(packageName) {
250
+ const encoded = packageName.startsWith("@") ? packageName.replace("/", "%2f") : packageName;
251
+ return `${REGISTRY}/${encoded}`;
252
+ }
253
+
254
+ /**
255
+ * The tarball URL. npm names the file after the package without its
256
+ * scope, so `@scope/name` publishes `name-<version>.tgz`.
257
+ */
258
+ function tarballUrl(packageName, version) {
259
+ const bare = packageName.startsWith("@") ? packageName.slice(packageName.indexOf("/") + 1) : packageName;
260
+ return `${REGISTRY}/${packageName}/-/${bare}-${version}.tgz`;
261
+ }
262
+
263
+ /**
264
+ * Probe one tarball. A HEAD is enough: the registry answers it with the
265
+ * same status it gives the GET, without moving the body.
266
+ *
267
+ * The three answers are kept apart on purpose:
268
+ *
269
+ * "gone" the registry answered 404. The content is not downloadable.
270
+ * "alive" the registry answered 200. The content is still there.
271
+ * "unknown" the registry did not answer. Nothing was proven.
272
+ */
273
+ async function probeTarball(packageName, version) {
274
+ try {
275
+ const response = await fetch(tarballUrl(packageName, version), { method: "HEAD" });
276
+ if (response.status === 404) return "gone";
277
+ if (response.status === 200) return "alive";
278
+ return "unknown";
279
+ } catch {
280
+ return "unknown";
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Run an async worker over a list with a bounded number in flight.
286
+ */
287
+ async function mapLimit(items, limit, worker) {
288
+ const results = [];
289
+ let next = 0;
290
+ const runner = async () => {
291
+ while (next < items.length) {
292
+ const index = next++;
293
+ results[index] = [items[index], await worker(items[index])];
294
+ }
295
+ };
296
+ const runners = [];
297
+ for (let i = 0; i < Math.min(limit, items.length); i++) runners.push(runner());
298
+ await Promise.all(runners);
299
+ return results;
300
+ }
301
+
302
+ process.exit(await main());