pi-harness-runtime 1.1.435 → 1.1.437

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 (122) hide show
  1. package/harness/key-file-audit.ts +103 -3
  2. package/harness/startup-report.ts +32 -1
  3. package/index.ts +28 -0
  4. package/package.json +2 -1
  5. package/packages/a2a-adapter/package.json +1 -1
  6. package/packages/agent-policy/package.json +1 -1
  7. package/packages/architecture-generator/package.json +1 -1
  8. package/packages/auth/package.json +1 -1
  9. package/packages/autonomous-refactor/package.json +1 -1
  10. package/packages/autonomous-runtime/package.json +1 -1
  11. package/packages/cache-strategy/package.json +1 -1
  12. package/packages/capability-registry/package.json +1 -1
  13. package/packages/checkpoint/package.json +1 -1
  14. package/packages/cli-plugin-sdk/package.json +1 -1
  15. package/packages/clipboard/package.json +1 -1
  16. package/packages/clipboard-plugin/package.json +1 -1
  17. package/packages/code-generation/package.json +1 -1
  18. package/packages/code-review/package.json +1 -1
  19. package/packages/codex-adapter/package.json +1 -1
  20. package/packages/codex-watcher/package.json +1 -1
  21. package/packages/config-capture/package.json +1 -1
  22. package/packages/connection-runtime/package.json +1 -1
  23. package/packages/context-compiler/package.json +1 -1
  24. package/packages/context-discovery/package.json +1 -1
  25. package/packages/context-manager/package.json +1 -1
  26. package/packages/contracts/package.json +1 -1
  27. package/packages/cookie-sanitizer/package.json +1 -1
  28. package/packages/cost-optimizer/package.json +1 -1
  29. package/packages/dependency-analyzer/package.json +1 -1
  30. package/packages/django-plugin/package.json +1 -1
  31. package/packages/doc-generator/package.json +1 -1
  32. package/packages/durable-review/package.json +1 -1
  33. package/packages/e2e-tester/package.json +1 -1
  34. package/packages/evaluation-engine/package.json +1 -1
  35. package/packages/evaluation-runner/package.json +1 -1
  36. package/packages/event-bus/package.json +1 -1
  37. package/packages/event-sink/package.json +1 -1
  38. package/packages/event-store/package.json +1 -1
  39. package/packages/experience-replay/package.json +1 -1
  40. package/packages/feedback-collector/package.json +1 -1
  41. package/packages/file-copy-helper/package.json +1 -1
  42. package/packages/framework-detector/package.json +1 -1
  43. package/packages/framework-plugin-sdk/package.json +1 -1
  44. package/packages/frappe-plugin/package.json +1 -1
  45. package/packages/generic-web-plugin/package.json +1 -1
  46. package/packages/health-monitor/package.json +1 -1
  47. package/packages/intent-analyzer/package.json +1 -1
  48. package/packages/jev-judge/package.json +1 -1
  49. package/packages/knowledge-graph/package.json +1 -1
  50. package/packages/knowledge-retrieval/package.json +1 -1
  51. package/packages/laravel-plugin/package.json +1 -1
  52. package/packages/learning-engine/package.json +1 -1
  53. package/packages/logging/package.json +1 -1
  54. package/packages/mcp-adapter/package.json +1 -1
  55. package/packages/memory-engine/package.json +1 -1
  56. package/packages/milestone-manager/package.json +1 -1
  57. package/packages/model-registry/package.json +1 -1
  58. package/packages/nextjs-plugin/package.json +1 -1
  59. package/packages/notification/package.json +1 -1
  60. package/packages/observability/package.json +1 -1
  61. package/packages/okf-indexer/package.json +1 -1
  62. package/packages/paperclip-integration/package.json +1 -1
  63. package/packages/performance-optimizer/package.json +1 -1
  64. package/packages/permission-mode/package.json +1 -1
  65. package/packages/privilege-broker/package.json +1 -1
  66. package/packages/project-analyzer/package.json +1 -1
  67. package/packages/project-bootstrap/package.json +1 -1
  68. package/packages/projection-engine/package.json +1 -1
  69. package/packages/prompt-compiler/package.json +1 -1
  70. package/packages/prompt-versioning/package.json +1 -1
  71. package/packages/provider-adapter-sdk/package.json +1 -1
  72. package/packages/provider-router/package.json +1 -1
  73. package/packages/provider-selector/package.json +1 -1
  74. package/packages/providers/package.json +1 -1
  75. package/packages/qdrant-skills/package.json +1 -1
  76. package/packages/quota-manager/package.json +1 -1
  77. package/packages/rate-limiter/package.json +1 -1
  78. package/packages/react-vite-plugin/package.json +1 -1
  79. package/packages/relay/package.json +1 -1
  80. package/packages/release-manager/package.json +1 -1
  81. package/packages/requirement-compiler/package.json +1 -1
  82. package/packages/runtime/package.json +1 -1
  83. package/packages/scheduler/package.json +1 -1
  84. package/packages/scheduler-adapter/package.json +1 -1
  85. package/packages/session/package.json +1 -1
  86. package/packages/session-api/package.json +1 -1
  87. package/packages/session-export/package.json +1 -1
  88. package/packages/shared-context/package.json +1 -1
  89. package/packages/skill-mcp-client/package.json +1 -1
  90. package/packages/skill-registry/package.json +1 -1
  91. package/packages/skills/package.json +1 -1
  92. package/packages/sprint-planner/package.json +1 -1
  93. package/packages/subscription-engine/package.json +1 -1
  94. package/packages/task-compiler/package.json +1 -1
  95. package/packages/tencentdb-memory/package.json +1 -1
  96. package/packages/tencentdb-sync/package.json +1 -1
  97. package/packages/test-data-generator/package.json +1 -1
  98. package/packages/test-generator/package.json +1 -1
  99. package/packages/todo-bd-sync/package.json +1 -1
  100. package/packages/token-estimation/package.json +1 -1
  101. package/packages/token-optimizer/package.json +1 -1
  102. package/packages/tooling-preference/package.json +1 -1
  103. package/packages/trajectory/package.json +1 -1
  104. package/packages/tui/package.json +1 -1
  105. package/packages/two-phase-review/package.json +1 -1
  106. package/packages/types/package.json +1 -1
  107. package/packages/voice-api/package.json +1 -1
  108. package/packages/webmcp-tester/package.json +1 -1
  109. package/packages/wiki/package.json +1 -1
  110. package/packages/workflow-events/package.json +1 -1
  111. package/packages/workspace-scanner/package.json +1 -1
  112. package/packages/worktree/package.json +1 -1
  113. package/packages/write-review/package.json +1 -1
  114. package/scripts/check-sensitive-terms.d.mts +116 -0
  115. package/scripts/check-sensitive-terms.mjs +764 -0
  116. package/scripts/guard-scan.sh +102 -0
  117. package/scripts/release/adapters/node-workspace.ts +1 -3
  118. package/scripts/release/orchestrator.ts +11 -5
  119. package/scripts/release/tsconfig.json +11 -0
  120. package/scripts/typecheck-packages.mjs +15 -2
  121. package/scripts/verify-package-contents.ts +69 -1
  122. package/scripts/tsconfig.json +0 -9
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env bash
2
+ # Scan the whole checkout for a client name.
3
+ #
4
+ # The checks that run in CI look at what a pull request changes. This one
5
+ # looks at everything: the files of the working tree, the paths of every
6
+ # ref of the repository, and the commit messages of every ref. It is the
7
+ # check to run when the question is "is this repository clean right now",
8
+ # and the check to run before a release that was prepared outside of a
9
+ # pull request.
10
+ #
11
+ # The list of terms comes from PI_SENSITIVE_TERMS_FILE or from
12
+ # SENSITIVE_TERMS. Without a list the script says so and stops - a
13
+ # machine that does not know the names cannot check for them, and a scan
14
+ # that found nothing is not a scan that passed.
15
+ #
16
+ # The report names the file and the line and never the term.
17
+
18
+ set -euo pipefail
19
+
20
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
21
+ cd "$ROOT"
22
+
23
+ SCANNER="scripts/check-sensitive-terms.mjs"
24
+
25
+ if [ ! -f "$SCANNER" ]; then
26
+ echo "guard: the scanner is missing at $SCANNER" >&2
27
+ exit 2
28
+ fi
29
+
30
+ # The list of terms, without printing it.
31
+ if [ -n "${PI_SENSITIVE_TERMS_FILE:-}" ] && [ -f "${PI_SENSITIVE_TERMS_FILE:-}" ]; then
32
+ TERMS="$(cat "$PI_SENSITIVE_TERMS_FILE")"
33
+ elif [ -n "${SENSITIVE_TERMS:-}" ]; then
34
+ TERMS="$SENSITIVE_TERMS"
35
+ else
36
+ echo "guard: no list of terms. Set PI_SENSITIVE_TERMS_FILE or SENSITIVE_TERMS."
37
+ echo "guard: the scan did not run, so nothing was checked."
38
+ exit 2
39
+ fi
40
+
41
+ if [ -z "$TERMS" ]; then
42
+ echo "guard: the list of terms is empty. The scan did not run."
43
+ exit 2
44
+ fi
45
+
46
+ COUNT="$(node --input-type=module -e '
47
+ import { readTermsFile, termsFromEnv } from "./scripts/check-sensitive-terms.mjs";
48
+ const terms = process.env.PI_SENSITIVE_TERMS_FILE
49
+ ? readTermsFile(process.env.PI_SENSITIVE_TERMS_FILE)
50
+ : termsFromEnv();
51
+ console.log(terms.length);
52
+ ')"
53
+ echo "guard: a list of ${COUNT} term(s)"
54
+
55
+ STATUS=0
56
+
57
+ # The working tree: the files and their paths.
58
+ echo "guard: the files and the paths of the working tree"
59
+ if ! node "$SCANNER" --tree .; then
60
+ STATUS=1
61
+ fi
62
+
63
+ # The commit messages of every ref. A message is public the moment the
64
+ # commit is pushed, and GitHub builds the release notes from them.
65
+ echo "guard: the commit messages of every ref"
66
+ if ! node "$SCANNER" --commits --all; then
67
+ STATUS=1
68
+ fi
69
+
70
+ # The paths of every ref. A name in a path is a name in a link to the
71
+ # repository, and the history of a path outlives the file.
72
+ echo "guard: the paths of every ref"
73
+ if ! node --input-type=module -e '
74
+ import { execFileSync } from "node:child_process";
75
+ import { pathHasTerm, termsFromEnv, redactTerms } from "./scripts/check-sensitive-terms.mjs";
76
+
77
+ const terms = termsFromEnv();
78
+ if (terms.length === 0) {
79
+ console.error("guard: no list of terms, so the paths were not checked.");
80
+ process.exit(2);
81
+ }
82
+ const output = execFileSync("git", ["log", "--all", "--name-only", "--pretty=format:"], {
83
+ encoding: "utf8",
84
+ maxBuffer: 64 * 1024 * 1024,
85
+ });
86
+ const paths = [...new Set(output.split("\n").map((line) => line.trim()).filter(Boolean))];
87
+ const hits = paths.filter((path) => pathHasTerm(path, terms));
88
+ for (const path of hits) {
89
+ console.log(`a path of the history holds a client name: ${redactTerms(path, terms)}`);
90
+ }
91
+ console.log(`guard: ${paths.length} path(s) of the history were checked`);
92
+ process.exit(hits.length > 0 ? 1 : 0);
93
+ '; then
94
+ STATUS=1
95
+ fi
96
+
97
+ if [ "$STATUS" -eq 0 ]; then
98
+ echo "guard: the repository holds no client name"
99
+ else
100
+ echo "guard: a client name is in the repository. See the places above."
101
+ fi
102
+ exit "$STATUS"
@@ -105,9 +105,7 @@ export const nodeWorkspaceAdapter: ReleaseAdapter = {
105
105
 
106
106
  // Must have workspaces field
107
107
  try {
108
- const raw = JSON.parse(
109
- readFileSync(rootPkg, "utf-8") as unknown as string,
110
- );
108
+ const raw = JSON.parse(readFileSync(rootPkg, "utf-8"));
111
109
  if (raw.workspaces) return 0.9;
112
110
  } catch {
113
111
  // ignore
@@ -12,14 +12,20 @@
12
12
  * The orchestrator handles the git/npm plumbing.
13
13
  */
14
14
 
15
+ // The imports below carry a `pi-lens-ignore` marker for TS5097. The language
16
+ // server that reads this file still holds a project configuration that no
17
+ // longer exists, and it reports the .ts specifiers as an error. The compiler
18
+ // does not - `npx tsc -p scripts/release/tsconfig.json` is clean - and Node
19
+ // needs the literal .ts specifiers, because its type stripping does not remap
20
+ // a .js specifier to a .ts file.
15
21
  import { execSync } from "node:child_process";
16
22
  import { existsSync } from "node:fs";
17
23
  import { resolve } from "path";
18
- import { detectStacks, formatProfile } from "./adapters/detector.ts";
19
- import { nodeWorkspaceAdapter } from "./adapters/node-workspace.ts";
20
- import { tauriAdapter } from "./adapters/tauri.ts";
21
- import { rustAdapter } from "./adapters/rust.ts";
22
- import { pythonAdapter } from "./adapters/python.ts";
24
+ import { detectStacks, formatProfile } from "./adapters/detector.ts"; // pi-lens-ignore: ts:5097
25
+ import { nodeWorkspaceAdapter } from "./adapters/node-workspace.ts"; // pi-lens-ignore: ts:5097
26
+ import { tauriAdapter } from "./adapters/tauri.ts"; // pi-lens-ignore: ts:5097
27
+ import { rustAdapter } from "./adapters/rust.ts"; // pi-lens-ignore: ts:5097
28
+ import { pythonAdapter } from "./adapters/python.ts"; // pi-lens-ignore: ts:5097
23
29
  import type { AdapterContext, ReleaseAdapter } from "./adapters/base.ts";
24
30
 
25
31
  const ADAPTERS: ReleaseAdapter[] = [
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "types": ["node"],
7
+ "noEmit": true,
8
+ "allowImportingTsExtensions": true
9
+ },
10
+ "include": ["./**/*.ts"]
11
+ }
@@ -36,7 +36,8 @@ const BASELINES = new Map([
36
36
  ["voice-api", 16],
37
37
  ["worktree", 0],
38
38
  ["harness", 20],
39
- ["scripts", 15],
39
+ ["scripts", 9],
40
+ ["scripts/release", 0],
40
41
  ["root", 2],
41
42
  ["new-modules", 0],
42
43
  ]);
@@ -67,11 +68,16 @@ for (const name of readdirSync(packagesDir).sort()) {
67
68
  const project = join(packagesDir, name, "tsconfig.json");
68
69
  if (existsSync(project)) projects.push(relative(root, project));
69
70
  }
70
- for (const extra of ["harness", "scripts"]) {
71
+ for (const extra of ["harness", "scripts/release"]) {
71
72
  if (existsSync(join(root, extra, "tsconfig.json"))) {
72
73
  projects.push(join(extra, "tsconfig.json"));
73
74
  }
74
75
  }
76
+ // The scripts of the repository are their own project, with a config
77
+ // of their own at the root of the repository.
78
+ if (existsSync(join(root, "tsconfig.scripts.json"))) {
79
+ projects.push("tsconfig.scripts.json");
80
+ }
75
81
  // The root extension (index.ts) has no project of its own - it is the entry
76
82
  // point of the extension and was never type checked.
77
83
  if (existsSync(join(root, "tsconfig.root.json"))) {
@@ -92,9 +98,16 @@ function ownerOf(projectPath) {
92
98
  const normalized = projectPath.split("\\").join("/");
93
99
  if (normalized === "tsconfig.root.json") return "root";
94
100
  if (normalized === "tsconfig.new-modules.json") return "new-modules";
101
+ if (normalized === "tsconfig.scripts.json") return "scripts";
95
102
  if (normalized.startsWith("packages/")) {
96
103
  return normalized.split("/")[1];
97
104
  }
105
+ // A project in a folder of its own (the release sources in
106
+ // scripts/release) is a project of its own, and not the project of
107
+ // the folder that holds it.
108
+ if (normalized.endsWith("/tsconfig.json")) {
109
+ return normalized.slice(0, -"/tsconfig.json".length);
110
+ }
98
111
  return normalized.split("/")[0];
99
112
  }
100
113
 
@@ -36,6 +36,12 @@ import {
36
36
  packageNameOf,
37
37
  resolveRelativeImport,
38
38
  } from "./lib/runtime-imports.js";
39
+ import {
40
+ readTermsFile,
41
+ redactTerms,
42
+ scanText,
43
+ termsFromEnv,
44
+ } from "./check-sensitive-terms.mjs";
39
45
 
40
46
  const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
41
47
  const verifyTarball = process.argv.includes("--pack");
@@ -48,7 +54,8 @@ interface Problem {
48
54
  | "missing-tarball"
49
55
  | "missing-package"
50
56
  | "forbidden-path"
51
- | "missing-plugin";
57
+ | "missing-plugin"
58
+ | "sensitive-content";
52
59
  detail: string;
53
60
  }
54
61
 
@@ -221,6 +228,66 @@ function checkPackageLayout(): void {
221
228
  }
222
229
  }
223
230
 
231
+ /**
232
+ * The terms of the list, and where they came from.
233
+ *
234
+ * The list is the repository secret, or the local file. A run without a
235
+ * list scans nothing - and says so, because "no name was found" and
236
+ * "nothing was looked at" are not the same statement.
237
+ */
238
+ function sensitiveTerms(): { terms: string[]; source: string } {
239
+ const fromEnv = termsFromEnv(process.env);
240
+ if (fromEnv.length > 0) return { terms: fromEnv, source: "the environment" };
241
+ const file = process.env.PI_SENSITIVE_TERMS_FILE;
242
+ if (file) {
243
+ const terms = readTermsFile(file);
244
+ if (terms.length > 0) return { terms, source: file };
245
+ }
246
+ return { terms: [], source: "none" };
247
+ }
248
+
249
+ /**
250
+ * The published files must not hold a client name.
251
+ *
252
+ * The other checks look at the paths of the published files. This one
253
+ * looks at what is inside them: a name in a comment, in a doc or in a
254
+ * string is published like any other byte, and npm keeps a published
255
+ * version for a long time - long enough that the removal of one becomes
256
+ * a support ticket.
257
+ *
258
+ * The report names the file and the line and never the term, and the
259
+ * path is printed with the terms hidden because a path is often the
260
+ * place the term is in.
261
+ */
262
+ function checkSensitiveContent(files: string[]): void {
263
+ const { terms, source } = sensitiveTerms();
264
+ if (terms.length === 0) {
265
+ // Nothing was checked. The release workflow runs this check on
266
+ // its own, with the secret, and it fails closed.
267
+ console.log(
268
+ "[verify-package-contents] the sensitive content scan was skipped: no term list is configured",
269
+ );
270
+ return;
271
+ }
272
+ for (const file of files) {
273
+ let content: string;
274
+ try {
275
+ content = readFileSync(join(ROOT, file), "utf8");
276
+ } catch {
277
+ continue;
278
+ }
279
+ for (const found of scanText(content, file, terms)) {
280
+ problems.push({
281
+ kind: "sensitive-content",
282
+ detail: `${redactTerms(found.path, terms)}:${found.line} holds a term from the sensitive list`,
283
+ });
284
+ }
285
+ }
286
+ console.log(
287
+ `[verify-package-contents] the sensitive content scan looked at ${files.length} published file(s) with the list of ${source}`,
288
+ );
289
+ }
290
+
224
291
  /**
225
292
  * The postinstall copies the plugin from the package root.
226
293
  *
@@ -596,6 +663,7 @@ if (publishedFiles.length === 0) {
596
663
  });
597
664
  } else {
598
665
  checkRelativeImports(publishedFiles);
666
+ checkSensitiveContent(publishedFiles);
599
667
  if (verifyTarball) inspectTarball(publishedFiles);
600
668
  }
601
669
 
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../tsconfig.base.json",
3
- "compilerOptions": {
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "types": ["node"]
7
- },
8
- "include": ["./**/*.ts"]
9
- }