vouchington-tooling 0.11.0 → 0.11.2

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 (66) hide show
  1. package/README.md +17 -0
  2. package/dist/agent-blackboard/snapshot-cleanup-receipt.mjs +2 -0
  3. package/dist/agent-blackboard/snapshot-cleanup-resume.d.mts +1 -1
  4. package/dist/agent-blackboard/snapshot-cleanup-resume.mjs +3 -6
  5. package/dist/agent-harness-config/apply.d.mts +4 -0
  6. package/dist/agent-harness-config/apply.mjs +72 -0
  7. package/dist/agent-harness-config/cli.d.mts +10 -0
  8. package/dist/agent-harness-config/cli.mjs +100 -0
  9. package/dist/agent-harness-config/index.d.mts +4 -0
  10. package/dist/agent-harness-config/index.mjs +3 -0
  11. package/dist/agent-harness-config/merge-json.d.mts +5 -0
  12. package/dist/agent-harness-config/merge-json.mjs +62 -0
  13. package/dist/agent-harness-config/merge-toml.d.mts +6 -0
  14. package/dist/agent-harness-config/merge-toml.mjs +132 -0
  15. package/dist/agent-harness-config/paths.d.mts +3 -0
  16. package/dist/agent-harness-config/paths.mjs +117 -0
  17. package/dist/agent-harness-config/policy.d.mts +14 -0
  18. package/dist/agent-harness-config/policy.mjs +51 -0
  19. package/dist/agent-harness-config/prerequisites.d.mts +2 -0
  20. package/dist/agent-harness-config/prerequisites.mjs +67 -0
  21. package/dist/agent-harness-config/toml-value.d.mts +6 -0
  22. package/dist/agent-harness-config/toml-value.mjs +69 -0
  23. package/dist/agent-harness-config/types.d.mts +88 -0
  24. package/dist/agent-harness-config/types.mjs +1 -0
  25. package/dist/browser-session-runner/watchdog.mjs +1 -0
  26. package/dist/cli/index.mjs +9 -6
  27. package/dist/cli/parse.d.mts +3 -0
  28. package/dist/cli/parse.mjs +2 -0
  29. package/dist/cli/usage.d.mts +1 -1
  30. package/dist/cli/usage.mjs +5 -0
  31. package/dist/gha-artifacts-cleanup/classify.mjs +1 -0
  32. package/dist/gha-post-review/claude-token.mjs +2 -0
  33. package/dist/gha-post-review/github.mjs +1 -0
  34. package/dist/gha-post-review/post.mjs +7 -1
  35. package/dist/gha-pr-checkpoint/codec.mjs +1 -0
  36. package/dist/gha-review-payload/diff.mjs +1 -0
  37. package/dist/gha-review-payload/payload.mjs +2 -0
  38. package/dist/gha-workspace-policy/shared.mjs +1 -0
  39. package/dist/http-link-pagination/index.mjs +1 -0
  40. package/dist/index.d.mts +2 -0
  41. package/dist/index.mjs +1 -0
  42. package/dist/pnpm-deploy/normalize.mjs +1 -0
  43. package/dist/pnpm-install/install-operations.d.mts +2 -1
  44. package/dist/pnpm-install/install-operations.mjs +16 -4
  45. package/dist/pnpm-install/metadata.d.mts +3 -3
  46. package/dist/pnpm-install/metadata.mjs +10 -24
  47. package/dist/pnpm-install/pending-builds.d.mts +6 -14
  48. package/dist/pnpm-install/pending-builds.mjs +23 -91
  49. package/dist/pnpm-install/pnpm-install-fake-pnpm.test-helpers.mjs +15 -1
  50. package/dist/pnpm-install/runner.mjs +27 -59
  51. package/dist/pnpm-install/transition.d.mts +2 -7
  52. package/dist/pnpm-install/transition.mjs +3 -11
  53. package/dist/runner-port-policy/index.mjs +2 -0
  54. package/dist/session-friction/log.mjs +1 -0
  55. package/dist/skill-discovery/manifest.mjs +2 -0
  56. package/dist/sql-ast/constraint-do-block.mjs +1 -0
  57. package/dist/sql-ast/drop-index.mjs +2 -0
  58. package/dist/vitest-blob-manifest/reports-cli.mjs +2 -0
  59. package/docs/agent-harness-config.md +134 -0
  60. package/package.json +8 -1
  61. package/dist/cli/commands/post-review.d.mts +0 -1
  62. package/dist/cli/commands/post-review.mjs +0 -4
  63. package/dist/cli/commands/stage-review-payload.d.mts +0 -1
  64. package/dist/cli/commands/stage-review-payload.mjs +0 -4
  65. package/dist/cli/commands/swift-semantic-equal.d.mts +0 -1
  66. package/dist/cli/commands/swift-semantic-equal.mjs +0 -4
@@ -47,7 +47,7 @@ function runtimePlatformIdentity() {
47
47
  platform: process.platform,
48
48
  });
49
49
  }
50
- export async function persistentMetadataFingerprintV4(runCapture) {
50
+ export async function persistentMetadataFingerprintV5(runCapture) {
51
51
  const workspaces = (await listWorkspaces(runCapture)).toSorted((left, right) => left.path.localeCompare(right.path));
52
52
  const pnpmVersion = await runCapture(['--version']);
53
53
  if (pnpmVersion.code !== 0)
@@ -73,16 +73,14 @@ export async function persistentMetadataFingerprintV4(runCapture) {
73
73
  function validStamp(value) {
74
74
  if (typeof value !== 'object' || value === null)
75
75
  return false;
76
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish the candidate stamp type before complete field validation
76
77
  const stamp = value;
77
- return (stamp.version === 4 &&
78
+ return (stamp.version === 5 &&
78
79
  typeof stamp.lastInvocationInstallScripts === 'boolean' &&
79
- typeof stamp.scriptsEnabledInstallSucceeded === 'boolean' &&
80
+ typeof stamp.scriptsEnabledInstallVerified === 'boolean' &&
80
81
  typeof stamp.provenance === 'object' &&
81
82
  stamp.provenance !== null &&
82
- componentNames.every((name) => typeof stamp.provenance?.[name] === 'string') &&
83
- (stamp.pendingDependencyBuilds === undefined ||
84
- (Array.isArray(stamp.pendingDependencyBuilds) &&
85
- stamp.pendingDependencyBuilds.every((id) => typeof id === 'string'))));
83
+ componentNames.every((name) => typeof stamp.provenance?.[name] === 'string'));
86
84
  }
87
85
  async function readPersistentMetadataState() {
88
86
  try {
@@ -97,11 +95,7 @@ async function readPersistentMetadataState() {
97
95
  : { kind: 'unsafe' };
98
96
  }
99
97
  }
100
- async function readPersistentMetadataStamp() {
101
- const state = await readPersistentMetadataState();
102
- return state.kind === 'stamp' ? state.stamp : undefined;
103
- }
104
- export async function persistentMetadataStatusV4(provenance) {
98
+ export async function persistentMetadataStatusV5(provenance) {
105
99
  const state = await readPersistentMetadataState();
106
100
  if (state.kind === 'missing')
107
101
  return { kind: 'absent' };
@@ -114,23 +108,15 @@ export async function persistentMetadataStatusV4(provenance) {
114
108
  : {
115
109
  kind: 'matching',
116
110
  lastInvocationInstallScripts: stamp.lastInvocationInstallScripts,
117
- pendingDependencyBuilds: stamp.pendingDependencyBuilds ?? [],
118
- scriptsEnabledInstallSucceeded: stamp.scriptsEnabledInstallSucceeded,
111
+ scriptsEnabledInstallVerified: stamp.scriptsEnabledInstallVerified,
119
112
  };
120
113
  }
121
- export async function writePersistentMetadataStampV4(provenance, installScripts, resetScriptsEnabledCapability, pendingDependencyBuilds) {
122
- const existing = await readPersistentMetadataStamp();
123
- const existingMatches = existing && componentNames.every((name) => existing.provenance[name] === provenance[name]);
114
+ export async function writePersistentMetadataStampV5(provenance, installScripts, scriptsEnabledInstallVerified) {
124
115
  const stamp = {
125
116
  lastInvocationInstallScripts: installScripts,
126
- pendingDependencyBuilds: (pendingDependencyBuilds ??
127
- (existingMatches ? existing.pendingDependencyBuilds : undefined) ??
128
- []).toSorted(),
129
117
  provenance,
130
- scriptsEnabledInstallSucceeded: installScripts ||
131
- (!resetScriptsEnabledCapability &&
132
- Boolean(existingMatches && existing.scriptsEnabledInstallSucceeded)),
133
- version: 4,
118
+ scriptsEnabledInstallVerified,
119
+ version: 5,
134
120
  };
135
121
  const stampPath = persistentMetadataStampPath();
136
122
  const directory = path.dirname(stampPath);
@@ -1,18 +1,10 @@
1
- export type PendingBuilds = {
2
- kind: 'known';
3
- ids: Set<string>;
1
+ export type PendingBuildState = {
2
+ kind: 'clear';
4
3
  } | {
5
- kind: 'unknown';
6
- };
7
- export type PendingBuildDelta = {
8
- kind: 'unknown';
4
+ ids: string[];
5
+ kind: 'pending';
9
6
  } | {
10
- kind: 'known';
11
- dependencyIds: string[];
12
- workspaceIds: string[];
7
+ kind: 'unknown';
13
8
  };
14
- export declare function pendingBuilds(): Promise<PendingBuilds>;
9
+ export declare function pendingBuilds(): Promise<PendingBuildState>;
15
10
  export declare function buildLedgersAllowNativeRepair(): Promise<boolean>;
16
- export declare function validDependencyBuildIds(ids: [string, ...string[]]): Promise<[string, ...string[]] | undefined>;
17
- export declare function clearPendingDependencyBuilds(ids: string[]): Promise<boolean>;
18
- export declare function pendingBuildDelta(before: PendingBuilds, after: PendingBuilds): Promise<PendingBuildDelta>;
@@ -1,104 +1,36 @@
1
- import { readFile, rename, rm, writeFile } from 'node:fs/promises';
1
+ import { readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { parse, stringify } from 'yaml';
4
- export async function pendingBuilds() {
5
- try {
6
- const value = parse(await readFile(path.join(process.cwd(), 'node_modules', '.modules.yaml'), 'utf8'));
7
- if (typeof value !== 'object' || value === null || Array.isArray(value))
8
- return { kind: 'unknown' };
9
- const pending = value.pendingBuilds ?? [];
10
- if (!Array.isArray(pending) || !pending.every((id) => typeof id === 'string'))
11
- return { kind: 'unknown' };
12
- return { kind: 'known', ids: new Set(pending) };
13
- }
14
- catch {
15
- return { kind: 'unknown' };
16
- }
17
- }
18
- export async function buildLedgersAllowNativeRepair() {
3
+ import { parse } from 'yaml';
4
+ async function buildLedgers() {
19
5
  try {
20
6
  const value = parse(await readFile(path.join(process.cwd(), 'node_modules', '.modules.yaml'), 'utf8'));
21
7
  if (typeof value !== 'object' || value === null || Array.isArray(value))
22
- return false;
23
- const record = value;
24
- const ignored = record.ignoredBuilds;
25
- const pending = record.pendingBuilds ?? [];
26
- return (Array.isArray(ignored) &&
27
- ignored.length === 0 &&
28
- Array.isArray(pending) &&
29
- pending.length === 0);
30
- }
31
- catch {
32
- return false;
33
- }
34
- }
35
- async function lockfileDependencyIds() {
36
- try {
37
- const lockfile = parse(await readFile(path.join(process.cwd(), 'pnpm-lock.yaml'), 'utf8'));
38
- if (typeof lockfile !== 'object' || lockfile === null || !('packages' in lockfile))
39
8
  return undefined;
40
- const packages = lockfile.packages;
41
- if (typeof packages !== 'object' || packages === null || Array.isArray(packages))
9
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- validate the parsed YAML object before reading its fields
10
+ const record = value;
11
+ const ignored = Object.hasOwn(record, 'ignoredBuilds') ? record.ignoredBuilds : undefined;
12
+ const pending = Object.hasOwn(record, 'pendingBuilds') ? record.pendingBuilds : [];
13
+ if ((ignored !== undefined &&
14
+ (!Array.isArray(ignored) || !ignored.every((id) => typeof id === 'string'))) ||
15
+ !Array.isArray(pending) ||
16
+ !pending.every((id) => typeof id === 'string'))
42
17
  return undefined;
43
- return new Set(Object.keys(packages));
18
+ return {
19
+ ignoredBuilds: ignored,
20
+ pendingBuilds: pending.length === 0 ? { kind: 'clear' } : { ids: pending.toSorted(), kind: 'pending' },
21
+ };
44
22
  }
45
23
  catch {
46
24
  return undefined;
47
25
  }
48
26
  }
49
- export async function validDependencyBuildIds(ids) {
50
- const packages = await lockfileDependencyIds();
51
- if (!packages || !ids.every((id) => packages.has(id)))
52
- return undefined;
53
- const [first, ...remaining] = ids.toSorted();
54
- return [first, ...remaining];
55
- }
56
- export async function clearPendingDependencyBuilds(ids) {
57
- const filename = path.join(process.cwd(), 'node_modules', '.modules.yaml');
58
- try {
59
- const value = parse(await readFile(filename, 'utf8'));
60
- if (typeof value !== 'object' || value === null || Array.isArray(value))
61
- return false;
62
- const record = value;
63
- if (!Array.isArray(record.pendingBuilds) ||
64
- !record.pendingBuilds.every((id) => typeof id === 'string'))
65
- return false;
66
- const ignored = record.ignoredBuilds ?? [];
67
- if (!Array.isArray(ignored) ||
68
- !ignored.every((id) => typeof id === 'string') ||
69
- ids.some((id) => ignored.includes(id)))
70
- return false;
71
- record.pendingBuilds = record.pendingBuilds.filter((id) => !ids.includes(id));
72
- const temporary = `${filename}.${process.pid}.tmp`;
73
- try {
74
- await writeFile(temporary, stringify(record));
75
- await rename(temporary, filename);
76
- }
77
- finally {
78
- await rm(temporary, { force: true });
79
- }
80
- return true;
81
- }
82
- catch {
83
- return false;
84
- }
27
+ export async function pendingBuilds() {
28
+ return (await buildLedgers())?.pendingBuilds ?? { kind: 'unknown' };
85
29
  }
86
- export async function pendingBuildDelta(before, after) {
87
- if (before.kind !== 'known' || after.kind !== 'known')
88
- return { kind: 'unknown' };
89
- const packages = await lockfileDependencyIds();
90
- if (!packages)
91
- return { kind: 'unknown' };
92
- const dependencyIds = [];
93
- const workspaceIds = [];
94
- for (const id of after.ids) {
95
- if (before.ids.has(id))
96
- continue;
97
- (packages.has(id) ? dependencyIds : workspaceIds).push(id);
98
- }
99
- return {
100
- kind: 'known',
101
- dependencyIds: dependencyIds.toSorted(),
102
- workspaceIds: workspaceIds.toSorted(),
103
- };
30
+ export async function buildLedgersAllowNativeRepair() {
31
+ const ledgers = await buildLedgers();
32
+ return (ledgers !== undefined &&
33
+ ledgers.ignoredBuilds !== undefined &&
34
+ ledgers.ignoredBuilds.length === 0 &&
35
+ ledgers.pendingBuilds.kind === 'clear');
104
36
  }
@@ -29,18 +29,32 @@ if [ "\${PNPM_FAIL_RELEASE_AGE_CALL:-0}" = "$calls" ]; then
29
29
  exit 1
30
30
  fi
31
31
  if [ -n "\${PNPM_SLEEP_SECONDS:-}" ]; then sleep "$PNPM_SLEEP_SECONDS"; fi
32
- if [ -n "\${PNPM_PENDING_BUILDS:-}" ]; then
32
+ if [ "\${PNPM_INVALID_PENDING_BUILDS:-0}" = 1 ]; then
33
+ mkdir -p "$PNPM_NODE_MODULES"
34
+ printf 'pendingBuilds: invalid\n' > "$PNPM_NODE_MODULES/.modules.yaml"
35
+ elif [ -n "\${PNPM_PENDING_BUILDS:-}" ]; then
33
36
  mkdir -p "$PNPM_NODE_MODULES"
34
37
  printf 'pendingBuilds: [%s]\\n' "$PNPM_PENDING_BUILDS" > "$PNPM_NODE_MODULES/.modules.yaml"
38
+ elif [ ! -f "$PNPM_NODE_MODULES/.modules.yaml" ]; then
39
+ mkdir -p "$PNPM_NODE_MODULES"
40
+ printf 'pendingBuilds: []\\n' > "$PNPM_NODE_MODULES/.modules.yaml"
35
41
  fi
36
42
  case " $* " in
37
43
  *' rebuild '*)
44
+ if [ "\${PNPM_REPAIR_NATIVE_ON_REBUILD:-0}" = 1 ]; then
45
+ cp "$PNPM_NATIVE_REPLACEMENT" "$PNPM_NATIVE_ADDON"
46
+ fi
38
47
  if [ "\${PNPM_REBUILD_INVALID_LEDGER:-0}" = 1 ]; then
39
48
  printf 'pendingBuilds: invalid\n' > "$PNPM_NODE_MODULES/.modules.yaml"
49
+ else
50
+ printf 'pendingBuilds: []\n' > "$PNPM_NODE_MODULES/.modules.yaml"
40
51
  fi
41
52
  if [ "\${PNPM_REBUILD_BREAK_LINK:-0}" = 1 ]; then rm -f "$PNPM_DEPENDENCY_LINK"; fi
42
53
  ;;
43
54
  *' --force '*)
55
+ if [ -z "\${PNPM_PENDING_BUILDS:-}" ]; then
56
+ printf 'pendingBuilds: []\n' > "$PNPM_NODE_MODULES/.modules.yaml"
57
+ fi
44
58
  if [ "\${PNPM_DELETE_NATIVE:-0}" = 1 ]; then
45
59
  rm -f "$PNPM_NATIVE_ADDON"
46
60
  elif [ "\${PNPM_REPAIR_NATIVE:-0}" = 1 ]; then
@@ -1,10 +1,10 @@
1
- import { persistentDependencyTreeIsCold, persistentMetadataFingerprintV4, persistentMetadataStatusV4, writePersistentMetadataStampV4, } from './metadata.mjs';
1
+ import { persistentDependencyTreeIsCold, persistentMetadataFingerprintV5, persistentMetadataStatusV5, writePersistentMetadataStampV5, } from './metadata.mjs';
2
2
  import { runPnpm } from './exec.mjs';
3
3
  import { mismatchedNativeBinaries } from './native-health.mjs';
4
4
  // oxfmt-ignore
5
- import { clearPendingDependencyBuilds, pendingBuildDelta, pendingBuilds, validDependencyBuildIds } from './pending-builds.mjs';
5
+ import { pendingBuilds } from './pending-builds.mjs';
6
6
  // oxfmt-ignore
7
- import { install, reconcileOrFail, repairIsolatedNativeMismatch, withScriptPolicy } from './install-operations.mjs';
7
+ import { finalizePendingBuilds, install, reconcileOrFail, repairIsolatedNativeMismatch, withScriptPolicy } from './install-operations.mjs';
8
8
  // oxfmt-ignore
9
9
  import { baseInstallArgs, findWorkspaceLinkMismatches, logWorkspaceLinkMismatches } from './support.mjs';
10
10
  import { persistentInstallTransition, persistentProvenanceDiagnostic } from './transition.mjs';
@@ -14,33 +14,30 @@ async function persistent(options) {
14
14
  if (options.ephemeralWorkspaces.trim())
15
15
  fail('ephemeral-workspaces is only valid for ephemeral runners');
16
16
  const runCapture = (args) => runPnpm(args, options, true);
17
- const fingerprint = await persistentMetadataFingerprintV4(runCapture);
18
- const provenance = await persistentMetadataStatusV4(fingerprint);
17
+ const fingerprint = await persistentMetadataFingerprintV5(runCapture);
18
+ const provenance = await persistentMetadataStatusV5(fingerprint);
19
+ const pendingBefore = await pendingBuilds();
19
20
  const mismatchedNatives = await mismatchedNativeBinaries();
20
21
  const nativesMatch = mismatchedNatives.length === 0;
21
22
  const repairedNativeMismatch = !nativesMatch &&
22
23
  provenance.kind === 'matching' &&
23
24
  (await repairIsolatedNativeMismatch(options, runCapture, mismatchedNatives));
24
25
  if (repairedNativeMismatch) {
26
+ const pendingAfterRepair = await finalizePendingBuilds(options, runCapture, 'native health reconciliation');
25
27
  console.warn('persistent optional native binaries do not match this runtime; reconciled');
26
28
  console.warn(persistentProvenanceDiagnostic(provenance, options.installScripts, nativesMatch, {
27
29
  action: 'reconcile',
28
30
  reason: 'native-health-mismatch',
29
31
  }));
30
- await writePersistentMetadataStampV4(fingerprint, options.installScripts, true, []);
32
+ await writePersistentMetadataStampV5(fingerprint, options.installScripts, options.installScripts || persistentStampRemainsVerified(provenance, pendingAfterRepair));
31
33
  return 'persistent native health reconciled';
32
34
  }
33
35
  const provisionalTransition = persistentInstallTransition(provenance, options.installScripts);
34
- let transition = nativesMatch
35
- ? provisionalTransition
36
- : { action: 'reconcile', reason: 'native-health-mismatch' };
37
- if (transition.action === 'upgrade-dependencies') {
38
- const ids = await validDependencyBuildIds(transition.pendingDependencyBuilds);
39
- if (!ids)
40
- transition = { action: 'upgrade-scripts', reason: 'invalid-pending-dependency-builds' };
41
- else
42
- transition = { ...transition, pendingDependencyBuilds: ids };
43
- }
36
+ const transition = !nativesMatch
37
+ ? { action: 'reconcile', reason: 'native-health-mismatch' }
38
+ : provenance.kind !== 'matching' || pendingBefore.kind === 'clear'
39
+ ? provisionalTransition
40
+ : { action: 'reconcile', reason: 'pending-build-ledger-unverified' };
44
41
  const provenanceOk = provenance.kind === 'matching' && transition.action !== 'reconcile' && nativesMatch;
45
42
  const cold = !provenanceOk && (await persistentDependencyTreeIsCold());
46
43
  if (!provenanceOk && !cold) {
@@ -51,54 +48,19 @@ async function persistent(options) {
51
48
  console.warn(provenance.kind === 'matching' && !nativesMatch
52
49
  ? 'persistent optional native binaries do not match this runtime; reconciling'
53
50
  : 'persistent dependency metadata provenance is missing or changed; reconciling');
54
- await reconcileOrFail(options, runCapture);
55
- await writePersistentMetadataStampV4(fingerprint, options.installScripts, true, []);
51
+ await reconcileOrFail(options);
52
+ const pendingAfterReconcile = await finalizePendingBuilds(options, runCapture, 'persistent reconciliation');
53
+ await writePersistentMetadataStampV5(fingerprint, options.installScripts, options.installScripts || persistentStampRemainsVerified(provenance, pendingAfterReconcile));
56
54
  return 'persistent metadata reconciled';
57
55
  }
58
56
  if (provenance.kind === 'absent')
59
57
  console.warn('persistent dependency tree is absent; installing cold');
60
- const pendingBefore = transition.action === 'ordinary' && !options.installScripts ? await pendingBuilds() : undefined;
61
- await install(withScriptPolicy([...baseInstallArgs], transition.action.startsWith('upgrade-') ? false : options.installScripts), options, 'ordinary persistent install');
58
+ await install(withScriptPolicy([...baseInstallArgs], options.installScripts), options, 'ordinary persistent install');
62
59
  const stale = await findWorkspaceLinkMismatches(runCapture);
63
60
  if (stale.length === 0) {
64
- if (transition.action.startsWith('upgrade-')) {
65
- const pendingDependencyBuilds = transition.action === 'upgrade-dependencies'
66
- ? transition.pendingDependencyBuilds
67
- : undefined;
68
- const rebuild = pendingDependencyBuilds === undefined
69
- ? ['rebuild', '--pending', '--recursive']
70
- : ['rebuild', '--recursive', '--', ...pendingDependencyBuilds];
71
- await install(rebuild, options, 'pending scripts rebuild');
72
- const rebuiltStale = await findWorkspaceLinkMismatches(runCapture);
73
- if (rebuiltStale.length > 0) {
74
- logWorkspaceLinkMismatches(rebuiltStale);
75
- await reconcileOrFail(options, runCapture);
76
- console.warn(persistentProvenanceDiagnostic(provenance, options.installScripts, nativesMatch, {
77
- action: 'reconcile',
78
- reason: 'workspace-links-stale-after-rebuild',
79
- }));
80
- await writePersistentMetadataStampV4(fingerprint, options.installScripts, true, []);
81
- return 'persistent reconciled';
82
- }
83
- if (pendingDependencyBuilds !== undefined &&
84
- !(await clearPendingDependencyBuilds(pendingDependencyBuilds)))
85
- fail('dependency rebuild completed but pending build ledger could not be updated safely');
86
- }
61
+ const pendingAfterInstall = await finalizePendingBuilds(options, runCapture, 'persistent install');
87
62
  console.warn(persistentProvenanceDiagnostic(provenance, options.installScripts, nativesMatch, transition));
88
- const pendingAfter = pendingBefore ? await pendingBuilds() : undefined;
89
- const delta = pendingBefore && pendingAfter
90
- ? await pendingBuildDelta(pendingBefore, pendingAfter)
91
- : undefined;
92
- const unsafePending = delta?.kind === 'unknown' || Boolean(delta?.workspaceIds.length);
93
- const pendingDependencyBuilds = transition.action.startsWith('upgrade-') || unsafePending
94
- ? []
95
- : [
96
- ...new Set([
97
- ...(provenance.kind === 'matching' ? provenance.pendingDependencyBuilds : []),
98
- ...(delta?.kind === 'known' ? delta.dependencyIds : []),
99
- ]),
100
- ].toSorted();
101
- await writePersistentMetadataStampV4(fingerprint, options.installScripts, unsafePending, pendingDependencyBuilds);
63
+ await writePersistentMetadataStampV5(fingerprint, options.installScripts, options.installScripts || persistentStampRemainsVerified(provenance, pendingAfterInstall));
102
64
  return provenance.kind === 'absent' ? 'persistent cold' : 'persistent ordinary';
103
65
  }
104
66
  logWorkspaceLinkMismatches(stale);
@@ -106,10 +68,16 @@ async function persistent(options) {
106
68
  action: 'reconcile',
107
69
  reason: 'workspace-links-stale',
108
70
  }));
109
- await reconcileOrFail(options, runCapture);
110
- await writePersistentMetadataStampV4(fingerprint, options.installScripts, true, []);
71
+ await reconcileOrFail(options);
72
+ const pendingAfterReconcile = await finalizePendingBuilds(options, runCapture, 'persistent reconciliation');
73
+ await writePersistentMetadataStampV5(fingerprint, options.installScripts, options.installScripts || persistentStampRemainsVerified(provenance, pendingAfterReconcile));
111
74
  return 'persistent reconciled';
112
75
  }
76
+ function persistentStampRemainsVerified(provenance, pending) {
77
+ return (provenance.kind === 'matching' &&
78
+ provenance.scriptsEnabledInstallVerified &&
79
+ pending.kind === 'clear');
80
+ }
113
81
  function isUnbracedPathClosureSelector(selector) {
114
82
  return /^\.{0,2}\//.test(selector) && selector.endsWith('...') && !selector.startsWith('{');
115
83
  }
@@ -6,17 +6,12 @@ export type ProvenanceStatus = {
6
6
  } | {
7
7
  kind: 'matching';
8
8
  lastInvocationInstallScripts: boolean;
9
- pendingDependencyBuilds: string[];
10
- scriptsEnabledInstallSucceeded: boolean;
9
+ scriptsEnabledInstallVerified: boolean;
11
10
  } | {
12
11
  kind: 'unsafe';
13
12
  };
14
13
  export type PersistentInstallTransition = {
15
- action: 'ordinary' | 'reconcile' | 'upgrade-scripts';
16
- reason: string;
17
- } | {
18
- action: 'upgrade-dependencies';
19
- pendingDependencyBuilds: [string, ...string[]];
14
+ action: 'ordinary' | 'reconcile';
20
15
  reason: string;
21
16
  };
22
17
  export declare function persistentInstallTransition(provenance: ProvenanceStatus, installScripts: boolean): PersistentInstallTransition;
@@ -2,15 +2,8 @@
2
2
  // evidence that this structural tree has already completed a scripts-enabled install.
3
3
  export function persistentInstallTransition(provenance, installScripts) {
4
4
  if (provenance.kind === 'matching') {
5
- if (installScripts && !provenance.scriptsEnabledInstallSucceeded)
6
- return { action: 'upgrade-scripts', reason: 'pending-scripts-rebuild' };
7
- const [firstPendingDependencyBuild, ...remainingPendingDependencyBuilds] = provenance.pendingDependencyBuilds;
8
- if (installScripts && firstPendingDependencyBuild !== undefined)
9
- return {
10
- action: 'upgrade-dependencies',
11
- pendingDependencyBuilds: [firstPendingDependencyBuild, ...remainingPendingDependencyBuilds],
12
- reason: 'pending-dependency-rebuild',
13
- };
5
+ if (installScripts && !provenance.scriptsEnabledInstallVerified)
6
+ return { action: 'reconcile', reason: 'scripts-enabled-install-unverified' };
14
7
  return { action: 'ordinary', reason: 'matching-structural-provenance' };
15
8
  }
16
9
  if (provenance.kind === 'absent')
@@ -26,9 +19,8 @@ export function persistentProvenanceDiagnostic(provenance, installScripts, nativ
26
19
  changedComponents: provenance.kind === 'changed' ? provenance.components : [],
27
20
  event: 'pnpm-install-persistent-provenance',
28
21
  installScripts,
29
- scriptsEnabledInstallSucceeded: provenance.kind === 'matching' ? provenance.scriptsEnabledInstallSucceeded : false,
22
+ scriptsEnabledInstallVerified: provenance.kind === 'matching' ? provenance.scriptsEnabledInstallVerified : false,
30
23
  lastInvocationInstallScripts: provenance.kind === 'matching' ? provenance.lastInvocationInstallScripts : null,
31
- pendingDependencyBuildCount: provenance.kind === 'matching' ? provenance.pendingDependencyBuilds.length : 0,
32
24
  nativeBinariesMatchRuntime,
33
25
  reason: transition.reason,
34
26
  state: provenance.kind,
@@ -33,6 +33,7 @@ export function validateRunnerPortPolicy(parsedPolicy, policyUrl) {
33
33
  if (typeof parsedPolicy !== 'object' || parsedPolicy === null || Array.isArray(parsedPolicy)) {
34
34
  throwInvalidPolicy(policyUrl);
35
35
  }
36
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish a record view after validating the untrusted policy object
36
37
  const policy = parsedPolicy;
37
38
  const requiredKeys = [
38
39
  'reservedPortStart',
@@ -45,6 +46,7 @@ export function validateRunnerPortPolicy(parsedPolicy, policyUrl) {
45
46
  requiredKeys.some((key) => !Number.isInteger(policy[key]))) {
46
47
  throwInvalidPolicy(policyUrl);
47
48
  }
49
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- retain the validated policy type after the complete key and value checks
48
50
  const validatedPolicy = policy;
49
51
  const { reservedPortStart: start, reservedPortEnd: end, portsPerRunner, minimumRunnerSlot, maximumRunnerSlot, } = validatedPolicy;
50
52
  if (start < 1 ||
@@ -30,6 +30,7 @@ function logPath(sessionId, directory) {
30
30
  function validEvent(value) {
31
31
  if (!value || typeof value !== 'object')
32
32
  return false;
33
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish a record view after the runtime object check
33
34
  const record = value;
34
35
  return ((record.kind === 'sandbox-escalation' || record.kind === 'sandbox-failure') &&
35
36
  isSafeAuditText(record.timestamp) &&
@@ -71,12 +71,14 @@ async function validateManifestEntries(root, entries) {
71
71
  function isManifest(value) {
72
72
  if (value === null || typeof value !== 'object')
73
73
  return false;
74
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish the candidate schema type after the runtime object check
74
75
  const manifest = value;
75
76
  return manifest.version === 1 && Array.isArray(manifest.skills) && manifest.skills.every(isEntry);
76
77
  }
77
78
  function isEntry(value) {
78
79
  if (value === null || typeof value !== 'object')
79
80
  return false;
81
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish the candidate schema type after the runtime object check
80
82
  const entry = value;
81
83
  return ([entry.name, entry.plugin, entry.pluginVersion, entry.path].every((field) => typeof field === 'string' && field.length > 0) &&
82
84
  (entry.prerequisites === undefined ||
@@ -33,6 +33,7 @@ export function processAlterTableStmt(statement, baseOffset, result, trackConstr
33
33
  if (!constraint)
34
34
  continue;
35
35
  if (constraint.contype === 'CONSTR_FOREIGN') {
36
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- isolate the generated AST type escape at the foreign-key adapter boundary
36
37
  const constraintRecord = constraint;
37
38
  result.foreignKeys.push(foreignKeyFromConstraint(constraintRecord, tableName, fkAttrNames(constraintRecord), baseOffset));
38
39
  }
@@ -9,6 +9,7 @@ export function extractDropIndexMetadata(content) {
9
9
  if (!node || !('DropStmt' in node) || node.DropStmt.removeType !== 'OBJECT_INDEX')
10
10
  continue;
11
11
  for (const object of node.DropStmt.objects ?? []) {
12
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish an unknown boundary before runtime shape validation
12
13
  const objectValue = object;
13
14
  const items = isRecord(objectValue) && isRecord(objectValue['List'])
14
15
  ? objectValue['List']['items']
@@ -16,6 +17,7 @@ export function extractDropIndexMetadata(content) {
16
17
  if (!Array.isArray(items))
17
18
  continue;
18
19
  const names = items.flatMap((item) => {
20
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish an unknown boundary before runtime shape validation
19
21
  const itemValue = item;
20
22
  const value = isRecord(itemValue) && isRecord(itemValue['String'])
21
23
  ? itemValue['String']['sval']
@@ -11,6 +11,7 @@ function parseContext(raw, attempt) {
11
11
  const parsed = JSON.parse(raw);
12
12
  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
13
13
  throw new Error('Vitest report expectation context must be an object');
14
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- establish a record view after validating the untrusted JSON object
14
15
  const context = parsed;
15
16
  if (Object.keys(context).toSorted().join('\0') !== ['attempt', 'suites', 'version'].join('\0') ||
16
17
  context.version !== 'vitest-report-expectations:v2' ||
@@ -26,6 +27,7 @@ function parseContext(raw, attempt) {
26
27
  Number(expectation.minimumAttempt) < 1 ||
27
28
  Number(expectation.minimumAttempt) > attempt))
28
29
  throw new Error('Vitest report expectation context has an invalid schema');
30
+ // oxlint-disable-next-line no-mistakes/ts-no-const-aliases -- retain the validated expectation type after the complete schema check
29
31
  const typed = context;
30
32
  const suites = typed.suites.map((expectation) => expectation.suite);
31
33
  if (new Set(suites).size !== suites.length || suites.join('\0') !== suites.toSorted().join('\0'))