@gfdelarue/testkit 0.5.0 → 0.6.1
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.
- package/README.md +590 -165
- package/bin/testkit-windows-owner-arm64.exe +0 -0
- package/bin/testkit-windows-owner-x64.exe +0 -0
- package/dist/app/bugs/batch.js +1 -0
- package/dist/app/bugs/ci-report.js +2 -2
- package/dist/app/bugs/ci-summary.js +3 -3
- package/dist/app/bugs/draft.js +2 -2
- package/dist/app/bugs/file.js +1 -1
- package/dist/app/bugs/guide.js +1 -1
- package/dist/app/bugs/record.js +2 -2
- package/dist/app/bugs/run-reading.js +1 -1
- package/dist/app/bugs/store.js +1 -1
- package/dist/app/campaigns/index.js +2 -2
- package/dist/app/campaigns/summary.js +1 -1
- package/dist/app/cleanup/index.js +1 -1
- package/dist/app/db-schema/prepare.js +1 -1
- package/dist/app/db-schema/refresh.js +1 -1
- package/dist/app/db-schema/verify.js +1 -1
- package/dist/app/destroy/index.js +1 -1
- package/dist/app/discover/index.js +2 -2
- package/dist/app/environments/config-driven.js +1 -1
- package/dist/app/environments/file-setup.js +1 -1
- package/dist/app/environments/routing.js +1 -1
- package/dist/app/environments/static-values.js +1 -1
- package/dist/app/environments/supplied.js +1 -1
- package/dist/app/inspect/index.js +1 -1
- package/dist/app/lint/native.js +1 -1
- package/dist/app/lint/options.js +1 -1
- package/dist/app/lint/shared.js +1 -1
- package/dist/app/run/engine-orchestration.js +1 -1
- package/dist/app/run/environment.js +1 -1
- package/dist/app/run/live-run.js +1 -1
- package/dist/app/run/orchestrator.js +1 -1
- package/dist/app/run/planning.js +1 -1
- package/dist/app/run/request.js +1 -1
- package/dist/app/run/results.js +1 -1
- package/dist/app/run/run-finalization.js +1 -1
- package/dist/app/run/run-finisher.js +1 -0
- package/dist/app/run/setup/runtime-node-setup-protocol.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-worker.js +1 -1
- package/dist/app/run/setup/runtime-node-setup.js +2 -2
- package/dist/app/run/task-batches.js +1 -1
- package/dist/app/run/worker-loop.js +1 -1
- package/dist/app/status/model.js +1 -1
- package/dist/app/status/runs.js +1 -1
- package/dist/app/stop/index.js +1 -1
- package/dist/app/tracker/index.js +1 -1
- package/dist/app/tracker/token.js +2 -2
- package/dist/app/typecheck/index.js +4 -4
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-flags.js +1 -1
- package/dist/cli/commands/artifacts.js +2 -2
- package/dist/cli/commands/bug/file.js +3 -2
- package/dist/cli/commands/discover.js +1 -1
- package/dist/cli/commands/guard/unsafe-entrypoint.js +1 -1
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/typecheck.js +1 -1
- package/dist/cli/commands/workspace.js +1 -1
- package/dist/cli/framework/help.js +5 -5
- package/dist/cli/framework/parser.js +1 -1
- package/dist/cli/json-errors.js +1 -1
- package/dist/cli/renderers/bug/text.js +1 -1
- package/dist/cli/renderers/run/formatting.js +1 -1
- package/dist/config/authoring/database-fixture-discovery.js +1 -0
- package/dist/config/authoring/index.js +1 -1
- package/dist/config/loader/config-loader.js +1 -1
- package/dist/config/loader/decode-discovery.js +1 -1
- package/dist/config/loader/discover-tests.js +1 -1
- package/dist/config/loader/discovery-result.js +1 -0
- package/dist/config/loader/discovery.js +2 -2
- package/dist/config/loader/file-metadata.js +1 -1
- package/dist/config/loader/groups.js +2 -1
- package/dist/config/loader/index.js +1 -1
- package/dist/config/loader/load.js +1 -1
- package/dist/config/loader/managed-configs.js +1 -1
- package/dist/config/loader/owned-discovery.js +1 -1
- package/dist/config/loader/runtime-isolation.js +1 -1
- package/dist/config/loader/skip-config.js +1 -1
- package/dist/config/loader/test-selection.js +1 -1
- package/dist/database/admin.js +5 -2
- package/dist/database/call-caps.js +1 -0
- package/dist/database/cleanup.js +1 -1
- package/dist/database/configured-steps.js +1 -1
- package/dist/database/constants.js +1 -1
- package/dist/database/docker-endpoint.js +1 -0
- package/dist/database/docker-metadata.js +2 -2
- package/dist/database/docker.js +5 -5
- package/dist/database/index.js +2 -1
- package/dist/database/lifecycle-cleanup.js +1 -1
- package/dist/database/local-postgres.js +4 -1
- package/dist/database/naming.js +1 -1
- package/dist/database/operation-deadline.js +1 -0
- package/dist/database/postgres/connection-check.js +1 -1
- package/dist/database/postgres/index.js +2 -2
- package/dist/database/postgres/owned-exec.js +27 -0
- package/dist/database/postgres/protocol.js +2 -2
- package/dist/database/provider.js +1 -0
- package/dist/database/roles.js +2 -2
- package/dist/database/schema-operations.js +5 -1
- package/dist/database/schema-source.js +3 -3
- package/dist/database/steps.js +1 -1
- package/dist/database/template-steps.js +4 -4
- package/dist/domain/identifiers.js +1 -1
- package/dist/domain/retired-test-types.js +1 -1
- package/dist/domain/suite-selection.js +1 -1
- package/dist/domain/test-types.js +1 -1
- package/dist/engines/adapters/evidence-files.js +1 -1
- package/dist/engines/adapters/execution.js +1 -1
- package/dist/engines/catalog.js +1 -1
- package/dist/engines/definitions.js +1 -1
- package/dist/engines/environment/index.js +1 -1
- package/dist/engines/installations/node-vitest.js +1 -1
- package/dist/engines/installations/playwright.js +1 -1
- package/dist/engines/managed-module-resolution.js +6 -2
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/node-vitest/adapter/driver.js +2 -2
- package/dist/engines/node-vitest/adapter/evidence.js +2 -2
- package/dist/engines/node-vitest/adapter/workspace.js +8 -24
- package/dist/engines/node-vitest/inventory/index.js +2 -2
- package/dist/engines/node-vitest/inventory/list-files.js +3 -3
- package/dist/engines/node-vitest/runtime/data/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/report.js +1 -1
- package/dist/engines/node-vitest/runtime/data/scenario.js +2 -2
- package/dist/engines/node-vitest/runtime/runtime-input.js +1 -1
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/browser-network-evidence.js +4 -0
- package/dist/engines/playwright/adapter/config.js +16 -6
- package/dist/engines/playwright/adapter/evidence.js +2 -1
- package/dist/engines/playwright/adapter/failure-details.js +2 -2
- package/dist/engines/playwright/adapter/reporter.js +1 -1
- package/dist/engines/playwright/runtime/browser-network.js +1 -0
- package/dist/engines/playwright/runtime/browser-traffic.js +1 -0
- package/dist/engines/playwright/runtime/chromium-environment.js +1 -0
- package/dist/engines/playwright/runtime/emulation.js +1 -0
- package/dist/engines/playwright/runtime/index.js +1 -1
- package/dist/engines/playwright/runtime/managed-test.js +1 -0
- package/dist/engines/playwright/runtime/runtime-input.js +2 -2
- package/dist/environment/lifecycle-controller.js +1 -1
- package/dist/environment/lifecycle.js +1 -1
- package/dist/environment/maintenance.js +1 -1
- package/dist/environment/run-environment.js +1 -1
- package/dist/environment/run-stopping.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/evidence/artifact-config.js +1 -1
- package/dist/evidence/artifacts.js +5 -2
- package/dist/evidence/bundles.js +2 -1
- package/dist/evidence/compressed-artifacts.js +1 -0
- package/dist/evidence/environment-record.js +1 -1
- package/dist/evidence/index.js +1 -1
- package/dist/evidence/live-run-summary.js +1 -0
- package/dist/evidence/local-paths.js +1 -0
- package/dist/evidence/maintenance.js +1 -0
- package/dist/evidence/operation-timings.js +1 -1
- package/dist/evidence/read-run.js +1 -1
- package/dist/evidence/redaction.js +4 -4
- package/dist/evidence/run-evidence.js +1 -0
- package/dist/evidence/setup-progress.js +1 -1
- package/dist/evidence/storage-inventory.js +1 -1
- package/dist/evidence/storage.js +2 -2
- package/dist/kernel/known-keys.js +1 -0
- package/dist/kernel/redaction-targets.js +1 -1
- package/dist/kernel/redaction.js +7 -4
- package/dist/process/engine-environment-keys.js +1 -0
- package/dist/process/environment-overlay.js +1 -1
- package/dist/process/environment.js +1 -1
- package/dist/process/execa-bundle.json +3 -3
- package/dist/process/files/evidence-writes.js +1 -0
- package/dist/process/files/product-dir.js +1 -1
- package/dist/process/host-process.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/lifecycle-fence.js +1 -1
- package/dist/process/lock-progress.js +2 -0
- package/dist/process/locks.js +4 -4
- package/dist/process/process-identity.js +1 -1
- package/dist/process/process.js +35 -35
- package/dist/process/recovery.js +1 -1
- package/dist/process/runs/manifest.js +1 -1
- package/dist/process/runs/ownership.js +1 -1
- package/dist/process/runs/stop.js +1 -1
- package/dist/process/shutdown.js +1 -1
- package/dist/process/windows-native.js +1 -1
- package/dist/repo/fingerprint-policy.js +1 -1
- package/dist/repo/history.js +7 -4
- package/dist/repo/managed-git.js +1 -1
- package/dist/repo/state.js +4 -4
- package/dist/steps/configured-step-testkit-modules.js +1 -1
- package/dist/steps/environment.js +1 -1
- package/dist/toolchains/index.js +2 -2
- package/dist/toolchains/node-provisioning.js +2 -2
- package/dist/toolchains/vitest/index.js +1 -1
- package/dist/tracker/gitea.js +1 -1
- package/dist/tracker/github.js +1 -1
- package/dist/tracker/http.js +1 -1
- package/dist/tracker/ownership.js +1 -0
- package/dist/tracker/redaction.js +1 -1
- package/dist/tracker/responses.js +1 -1
- package/dist/types/config.d.ts +7 -86
- package/dist/types/environment.d.ts +6 -0
- package/dist/types/node-vitest-data.d.ts +2 -218
- package/dist/types/playwright.d.ts +21 -0
- package/dist/types/workspace.d.ts +30 -14
- package/docs/bug-records.md +19 -18
- package/docs/engines.md +115 -21
- package/docs/release-notes.md +2846 -0
- package/docs/test-types.md +19 -69
- package/package.json +15 -6
- package/testkit-config-schema.md +101 -170
- package/dist/app/lint/rules/data.js +0 -1
- package/dist/config/authoring/runtime.js +0 -1
- package/dist/config/loader/task-policy.js +0 -1
- package/dist/engines/node-vitest/runtime/contract/index.js +0 -1
- package/dist/engines/node-vitest/runtime/data/http.js +0 -1
- package/dist/engines/node-vitest/runtime/data/runner.js +0 -1
- package/dist/environment/lifecycle-artifacts.js +0 -1
- package/dist/types/node-vitest-contract.d.ts +0 -75
|
@@ -1 +1 @@
|
|
|
1
|
-
import c from"node:fs/promises";import
|
|
1
|
+
import c from"node:fs/promises";import P from"node:os";import a from"node:path";import{toError as w}from"../kernel/error-serialization.js";import{isUnknownRecord as T}from"../kernel/unknown-values.js";import{captureProcessCreationIdentity as N,observeProcessCreationIdentity as O}from"./process-identity.js";const y="testkit-engine-",v=".testkit-owner.json",h=new Set;export async function createInvocationProcessEnvironment(t,r=process.env,e=process.platform){const o=a.join(t,"tmp");return E(t,o,!0,r,e)}export async function createNativeInvocationProcessEnvironment(t,r={}){const e=r.platform??process.platform,o=r.ambientEnvironment??process.env,u=await g(r.nativeTemporaryRootDirectory??I(o,e)),s=await R(e);h.has(u)||(h.add(u),await b(u,e,s));let i=null;try{const n=await c.mkdtemp(a.join(u,y));return i=n,e!=="win32"&&await c.chmod(n,448),i=await j(n,u,e),await c.writeFile(a.join(i,v),JSON.stringify({pid:process.pid,pidNamespace:s,processIdentity:N(process.pid)}),{flag:"wx",mode:384}),await E(t,i,!1,o,e)}catch(n){if(i===null)throw n;try{await c.rm(i,{force:!0,recursive:!0})}catch(m){throw new AggregateError([w(n),w(m)],`Could not initialize or remove native invocation temporary directory ${i}`,{cause:m})}throw n}}async function E(t,r,e,o,u){if(!a.isAbsolute(t))throw new Error("Engine invocation directory must be absolute");if(!a.isAbsolute(r))throw new Error("Engine invocation temporary directory must be absolute");const s=a.join(t,"home"),i=a.join(t,"cache"),n=a.join(t,"config"),m=a.join(t,"data"),d=a.join(t,"local-app-data"),f=a.join(t,"app-data");await Promise.all([s,...e?[r]:[],i,n,m,d,f].map(A=>c.mkdir(A,{mode:448})));const p={APPDATA:f,HOME:s,LOCALAPPDATA:d,TEMP:r,TMP:r,TMPDIR:r,USERPROFILE:s,XDG_CACHE_HOME:i,XDG_CONFIG_HOME:n,XDG_DATA_HOME:m};return l(p,o,"LANG"),l(p,o,"LC_ALL"),u==="win32"&&(p.PATH="",l(p,o,"ComSpec"),l(p,o,"SystemRoot")),Object.freeze({environment:Object.freeze(p),homeDirectory:s,temporaryDirectory:r})}async function R(t){if(t!=="linux")return null;try{return await c.readlink("/proc/self/ns/pid")}catch{return null}}async function b(t,r,e){if(r==="linux"&&e===null)return;let o;try{o=await c.readdir(t)}catch{return}for(const u of o.filter(s=>s.startsWith(y))){const s=a.join(t,u);try{const i=await c.lstat(s);if(!i.isDirectory()||i.isSymbolicLink()||r!=="win32"&&(i.uid!==process.getuid?.()||(i.mode&63)!==0))continue;const n=JSON.parse(await c.readFile(a.join(s,v),"utf8"));if(!T(n)||n.pidNamespace!==e||O(n.pid,n.processIdentity)!=="different")continue;await c.rm(s,{force:!0,recursive:!0})}catch{continue}}}async function g(t){if(!a.isAbsolute(t))throw new Error("Native invocation temporary root must be absolute");const r=await c.realpath(t);if(!(await c.stat(r)).isDirectory())throw new Error("Native invocation temporary root must be a directory");return r}async function j(t,r,e){const o=await c.lstat(t);if(!o.isDirectory()||o.isSymbolicLink())throw new Error("Native invocation temporary directory must be a non-symbolic-link directory");if(e!=="win32"&&(o.mode&63)!==0)throw new Error("Native invocation temporary directory must not grant group or other access");const u=await c.realpath(t);if(a.dirname(u)!==r)throw new Error("Native invocation temporary directory escaped its operating-system root");return u}function I(t,r){if(r!=="win32")return"/tmp";const e=t.TEMP??t.TMP;return e===void 0||e.length===0?P.tmpdir():e}function l(t,r,e){const o=r[e];o!==void 0&&(t[e]=o)}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"entrypoint": "dist/process/process.js",
|
|
4
|
-
"sourceSha256": "
|
|
5
|
-
"bundleSha256": "
|
|
6
|
-
"packageLockSha256": "
|
|
4
|
+
"sourceSha256": "e7301ca010796bb92d983c039db47f36e155c26ccfb42ff2d057d47addab3121",
|
|
5
|
+
"bundleSha256": "db5da25a23e4577451c0c047360de70af8abbd63be686dd7b97d65486cbba3b8",
|
|
6
|
+
"packageLockSha256": "0b4351d48801de63d0a5ceb85a7eac01fc24259d3cc3537f18ee0cd5db5101be",
|
|
7
7
|
"esbuildVersion": "0.28.1",
|
|
8
8
|
"options": {
|
|
9
9
|
"format": "esm",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import r from"node:fs";import{isWorkObserved as i,recordWork as o}from"../../kernel/work-metrics.js";export function recordEvidenceWrite(e){i()&&o(r.existsSync(e)?"evidence.filesRewritten":"evidence.filesWritten")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import i from"node:fs";import n from"node:path";import{hasErrorCode as s}from"../../kernel/error-serialization.js";export function resolveProductDir(o,e){const r=e?n.resolve(o,e):o;if(!i.existsSync(r))throw new Error(`Product directory does not exist: ${r}`);return protectTestkitStateRoot(r,!1),r}export function protectTestkitStateRoot(o,e){const r=n.join(o,".testkit");let t;try{t=i.lstatSync(r)}catch(d){if(!e||!s(d,"ENOENT"))return;try{i.mkdirSync(r,{mode:448})}catch(c){if(!s(c,"EEXIST"))throw c}return}if(!(process.platform==="win32"||!t.isDirectory()||(t.mode&63)===0)&&t.uid===process.getuid?.())try{i.chmodSync(r,t.mode&448)}catch{return}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import f from"node:fs";import s from"node:path";import{runManagedProcess as E,startSupervisedProcess as l}from"./process.js";import{hasErrorCode as m}from"../kernel/error-serialization.js";export function runManagedHostProcess(e){const
|
|
1
|
+
import f from"node:fs";import s from"node:path";import{runManagedProcess as E,startSupervisedProcess as l}from"./process.js";import{hasErrorCode as m}from"../kernel/error-serialization.js";export function runManagedHostProcess(e){const o=p(e);return E(o)}export function startManagedHostProcess(e){const o=p(e);return e.recoveryIdentity==="none"?l({...o,outputMode:e.outputMode,recoveryIdentity:"none"}):l({...o,outputMode:e.outputMode})}export function managedHostProcessInfrastructureError(e,o){const r=[];if(o.terminationError&&r.push(`process-scope termination was incomplete: ${o.terminationError.message}`),o.error&&r.push(`could not execute: ${o.error.message}`),o.timedOut&&r.push("exceeded its managed deadline"),o.cancelled&&r.push("was cancelled"),o.outputLimitExceeded&&r.push("exceeded the managed stdout/stderr capture limit"),r.length===0)return null;const n=new Error(`${e} ${r.join("; ")}`);return Object.defineProperty(n,"result",{enumerable:!1,value:Object.freeze({...o})}),n}export function normalizeManagedHostEnvironment(e=process.env,o=process.platform){const r=Object.entries(e).filter(t=>typeof t[1]=="string");if(o!=="win32")return Object.fromEntries(r);const n=new Map;for(const[t,a]of r){const c=t.toLowerCase();n.set(c,{key:y(c,t),value:a})}return Object.fromEntries([...n.entries()].sort(([t],[a])=>t.localeCompare(a)).map(([,t])=>[t.key,t.value]))}export function resolveManagedHostExecutable(e,o,r,n=process.platform){const t=resolveManagedHostExecutableIfAvailable(e,o,r,n);if(t)return t;throw r.PATH?new Error(`Could not resolve managed host executable ${JSON.stringify(e)}`):new Error(`Could not resolve managed host executable ${JSON.stringify(e)} because PATH is unavailable`)}export function resolveManagedHostExecutableIfAvailable(e,o,r,n=process.platform){if(e.trim().length===0)throw new Error("Managed host process executable must be non-empty");if(!s.isAbsolute(o))throw new Error("Managed host process working directory must be absolute");if(s.isAbsolute(e))return w(e,n);if(e.includes("/")||e.includes("\\"))throw new Error(`Managed host process executable paths must be absolute, got ${JSON.stringify(e)}`);const t=r.PATH;if(!t)return null;const a=b(e,r,n),c=n==="win32"?";":":";for(const u of t.split(c)){if(u.length===0)continue;const h=s.isAbsolute(u)?u:s.resolve(o,u);for(const g of a){const d=s.join(h,`${e}${g}`);try{const i=f.statSync(d,{throwIfNoEntry:!1});if(i!==void 0&&i.isFile()&&(n==="win32"||(i.mode&73)!==0))return w(d,n)}catch(i){if(!m(i,"ENOENT")&&!m(i,"ENOTDIR"))throw i}}}return null}function p(e){const o=s.resolve(e.cwd),r=normalizeManagedHostEnvironment(e.env);return{args:e.args,cwd:o,displayLabel:e.displayLabel,env:r,executable:resolveManagedHostExecutable(e.executable,o,r),signal:e.signal??new AbortController().signal,timeoutMs:e.timeoutMs,...e.timeoutStartsWhenReady===void 0?{}:{timeoutStartsWhenReady:e.timeoutStartsWhenReady},windowsVerbatimArguments:e.windowsVerbatimArguments,workPurpose:e.workPurpose}}function b(e,o,r){return r!=="win32"?[""]:s.extname(e).length>0?[""]:(o.PATHEXT||".COM;.EXE").split(";").map(t=>t.trim()).filter(t=>[".com",".exe"].includes(t.toLowerCase()))}function w(e,o){if(o==="win32"&&[".bat",".cmd"].includes(s.extname(e).toLowerCase()))throw new Error(`Windows batch wrappers are not managed host executables: ${e}`);const r=f.statSync(e);if(!r.isFile())throw new Error(`Managed host executable is not a regular file: ${e}`);if(o!=="win32"&&(r.mode&73)===0)throw new Error(`Managed host executable is not executable: ${e}`);return e}function y(e,o){return e==="path"?"PATH":e==="pathext"?"PATHEXT":e==="comspec"?"ComSpec":o}
|
package/dist/process/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{runManagedProcess,ProcessExitedBeforeReadyError,startSupervisedProcess,terminateAttributedProcessLineage,terminateOwnedPosixProcessGroup}from"./process.js";export{managedHostProcessInfrastructureError,normalizeManagedHostEnvironment,resolveManagedHostExecutable,resolveManagedHostExecutableIfAvailable,runManagedHostProcess,startManagedHostProcess}from"./host-process.js";export{requireManagedHostCommandSuccess,runManagedHostCommand}from"./host-command.js";export{resolvePosixCommandShell}from"./command-shell.js";export{captureOutput}from"./capture-output.js";export{captureProcessCreationIdentity,observeProcessCreationIdentity,processCreationIdentityMatches}from"./process-identity.js";export{createInvocationProcessEnvironment,createNativeInvocationProcessEnvironment
|
|
1
|
+
export{runManagedProcess,ProcessExitedBeforeReadyError,startSupervisedProcess,terminateAttributedProcessLineage,terminateOwnedPosixProcessGroup}from"./process.js";export{managedHostProcessInfrastructureError,normalizeManagedHostEnvironment,resolveManagedHostExecutable,resolveManagedHostExecutableIfAvailable,runManagedHostProcess,startManagedHostProcess}from"./host-process.js";export{requireManagedHostCommandSuccess,runManagedHostCommand}from"./host-command.js";export{resolvePosixCommandShell}from"./command-shell.js";export{captureOutput}from"./capture-output.js";export{captureProcessCreationIdentity,observeProcessCreationIdentity,processCreationIdentityMatches}from"./process-identity.js";export{createInvocationProcessEnvironment,createNativeInvocationProcessEnvironment}from"./environment.js";export{ENGINE_PROCESS_RESERVED_ENVIRONMENT_KEYS}from"./engine-environment-keys.js";export{installManagedProcessEnvironmentOverlay,managedProcessEnvironmentOverlayInstallerSource,MANAGED_PROCESS_ENVIRONMENT_OVERLAY_STATE_SYMBOL}from"./environment-overlay.js";export{DEFAULT_SHUTDOWN_TIMEOUT_MS}from"./shutdown.js";export{startReadyDeadline}from"./ready-deadline.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import o from"node:fs";import r from"node:path";import{protectTestkitStateRoot as a}from"./files/product-dir.js";import{withProcessLock as l}from"./locks.js";const s=Object.freeze([".testkit","_locks"]),f="run-maintenance.lock",d=Symbol("ProductLifecycleFence"),n=new WeakSet;export function resolveProductLifecycleLockPath(e){const t=o.realpathSync.native(r.resolve(e));return r.join(t,...s,f)}export async function withProductLifecycleFence(e,t,u={}){const c=E(e),i=resolveProductLifecycleLockPath(c.productDir);return a(c.productDir,!0),o.mkdirSync(r.dirname(i),{recursive:!0}),l(i,()=>L(c,t),{signal:u.signal,timeoutMs:null})}export function requireProductLifecycleFenceProductDir(e){if(!n.has(e))throw new Error("Product lifecycle mutation requires an active lifecycle fence");return e.productDir}function E(e){return Object.freeze({[d]:!0,productDir:o.realpathSync.native(r.resolve(e))})}async function L(e,t){n.add(e);try{return await t(e)}finally{n.delete(e)}}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{AsyncLocalStorage as i}from"node:async_hooks";import{randomUUID as S}from"node:crypto";import o from"node:fs";import f from"node:path";import{isUnknownRecord as g}from"../kernel/unknown-values.js";const p="progress.json",s=new i,a=new i,l=new i;export function runWithHeldProcessLockClaim(r,t){const e=a.getStore();return e!==void 0&&u([r],e),s.run([...s.getStore()??[],r],async()=>t())}export async function withProcessLockProgress(r,t){const e=a.getStore(),n={startedAt:new Date().toISOString(),step:r};u(s.getStore()??[],n);try{return await a.run(n,t)}finally{u(s.getStore()??[],e??null)}}export function observeProcessLockWaits(r,t){return l.run(r,t)}export function noteProcessLockWait(r){return l.getStore()?.(r)}export function describeProcessLockProgress(r){const t=m(r);return t===null?"; its progress is unknown":`; its current step: ${t.step}, for ${formatSeconds(Date.now()-Date.parse(t.startedAt))}`}export function formatSeconds(r){return`${(Math.max(0,r)/1e3).toFixed(1)} s`}function u(r,t){for(const e of r){const n=f.join(e.claimDirectory,p),c=`${n}.${S()}`;try{if(!e.intact())continue;if(t===null){o.rmSync(n,{force:!0});continue}o.writeFileSync(c,`${JSON.stringify(t)}
|
|
2
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),o.renameSync(c,n)}catch{try{o.rmSync(c,{force:!0})}catch{continue}}}}function m(r){try{const t=JSON.parse(o.readFileSync(f.join(r,p),"utf8"));return!g(t)||typeof t.step!="string"||typeof t.startedAt!="string"||Number.isNaN(Date.parse(t.startedAt))?null:{startedAt:t.startedAt,step:t.step}}catch{return null}}
|
package/dist/process/locks.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{AsyncLocalStorage as
|
|
2
|
-
`,{encoding:"utf8",flag:"wx",mode:384}),i.writeFileSync(
|
|
3
|
-
`,{encoding:"utf8",flag:"wx",mode:384})}catch(r){throw i.rmSync(e,{force:!0,recursive:!0}),r}}function
|
|
4
|
-
`,{encoding:"utf8",flag:"wx",mode:384}),i.rmSync(
|
|
1
|
+
import{AsyncLocalStorage as Ie}from"node:async_hooks";import{randomUUID as D}from"node:crypto";import i from"node:fs";import Re from"node:os";import a from"node:path";import{setTimeout as G}from"node:timers/promises";import{captureProcessCreationIdentity as J,inspectProcessLiveness as Le,sameProcessCreationIdentity as Q}from"./process-identity.js";import{retireWindowsClaim as Te}from"./windows-native.js";import{channel as Ae}from"node:diagnostics_channel";const L=Ae("testkit.work");import{isUnknownRecord as Z}from"../kernel/unknown-values.js";import{describeProcessLockProgress as z,formatSeconds as ge,noteProcessLockWait as _e,runWithHeldProcessLockClaim as Me}from"./lock-progress.js";export{observeProcessLockWaits,withProcessLockProgress}from"./lock-progress.js";import{hasErrorCode as u}from"../kernel/error-serialization.js";function Ce(e){try{i.mkdirSync(e,{mode:448})}catch(t){if(!u(t,"EEXIST"))throw t}return te(e)}function Oe(e){try{const t=i.lstatSync(e);return t.isDirectory()&&!t.isSymbolicLink()?"real":"unsafe"}catch(t){if(u(t,"ENOENT"))return"absent";throw t}}function ee(e){const t=i.lstatSync(e,{bigint:!0});if(!t.isDirectory()||t.isSymbolicLink())throw new Error(`Process lock path is not a real directory: ${e}`);return{birthtimeNs:t.birthtimeNs,dev:t.dev,ino:t.ino}}function te(e){try{return ee(e)}catch(t){if(u(t,"ENOENT")||Pe(t))return null;throw t}}function y(e,t){return re(te(e),t)}function re(e,t){return e!==null&&e.birthtimeNs===t.birthtimeNs&&e.dev===t.dev&&e.ino===t.ino}export function processLockClaimPublicationState(e,t,r){if(y(e,t))try{return Y(r)?"unsafe":"retry"}catch(o){if(C(o))return"retry";throw o}return y(r,t)?"published":"unsafe"}function Pe(e){return e instanceof Error&&e.message.startsWith("Process lock path is not a real directory:")}const ne="owner.json",W=1,x="claim-",U="choosing",oe="ticket",se=100,ie=65e3,$e=100,ve=new Set(["EACCES","EBUSY","EPERM"]),De=1e4,We=3,xe=20,Ue=5,je=20,Fe=5e3,ce=Re.hostname(),Ke=process.platform==="win32"?Fe:0,j=new Ie,F=new Set;class ae extends Error{constructor(t,r){super(`Timed out waiting for process lock ${a.basename(t)}${ft(r?.ownerRecord??null)}`+(r===null?"":z(r.claimDirectory))),this.name="ProcessLockTimeoutError"}}class Ve extends Error{constructor(t,r){super(`Process lock ${a.basename(t)} has a claim from this process, made at ${String(r.ownerRecord?.createdAt)}, that no operation in it holds. A release of it failed; it clears when this process exits: ${r.claimDirectory}`),this.name="ProcessLockLeakedClaimError"}}export async function withProcessLock(e,t,r={}){const n=be(e);at(n);const{claim:o,release:s}=await qe(n,r),c=new Set(j.getStore()??[]);c.add(n);try{return await j.run(c,()=>Me(o,t))}finally{await s()}}export async function tryWithProcessLock(e,t,r={}){let n;try{n=await withProcessLock(e,async()=>{try{return{ok:!0,value:await t()}}catch(o){return{error:o,ok:!1}}},{...r,timeoutMs:0})}catch(o){if(o instanceof ae)return{acquired:!1};throw o}if(!n.ok)throw n.error;return{acquired:!0,value:n.value}}export function probeProcessLock(e,t={}){const r=be(e),n=Se(r);if(!Y(n))return"absent";const o=t.identityObservations??new Map,s=fe(n,le(n),o,ue(),t);return s.rootAvailable&&s.claims.length===0?(V(n),"absent"):"active"}async function qe(e,t){const r=dt(t.timeoutMs,null,"process lock timeout"),n=mt(t.retryIntervalMs,se,"process lock retry interval");let o=t.retryIntervalMs===void 0?10:n;async function s(){const m=o;o=Math.min(n,o*2),await ut(m,t.signal,e)}const c=t.identityObservations??new Map,k=ue(),f=async m=>fe(d,await A(()=>le(d,m),t.signal,e),c,k,t),p=J(process.pid);if(p===null)throw new Error(`Cannot acquire process lock ${e}: current process creation identity is unavailable`);const S=Date.now(),N={createdAt:new Date(S).toISOString(),hostname:ce,pid:process.pid,processIdentity:p,schemaVersion:W,token:D()},d=Se(e),l=a.join(d,`${x}${N.token}`),I=`${d}.preparing-${N.token}`;Xe(I,N);let E=null,H=!1,R=null,_=!1,X=0,B=null,P;try{for(E=ee(I);;){g(t.signal,e);const b=await A(()=>Ce(d),t.signal,e);if(b!==null){try{i.renameSync(I,l),_=!0,R=b}catch(h){if(!u(h,"ENOENT"))if(C(h)){const w=processLockClaimPublicationState(I,E,l);if(w==="published")_=!0,R=b;else if(w==="retry"&&X<$e)X+=1;else throw h}else throw h}if(_){if(!y(d,b))throw new Error(`Process lock directory changed during claim publication: ${d}`);if(!y(l,E))throw new Error(`Process lock claim changed during publication: ${l}`);break}}else await f(null);O(e,null,S,r),await s()}if(R===null)throw new Error(`Process lock claim was published without its directory identity: ${l}`);const m=R;let T=nextProcessLockTicket((await f(m)).claims);for(;T===null;)O(e,null,S,r),await s(),T=nextProcessLockTicket((await f(m)).claims);const M=T;Be(l,M);const $=performance.now();for(;;){g(t.signal,e);const b=await f(m),h=b.claims.find(v=>v.claimDirectory===l);if(h?.state==="changing"){O(e,null,S,r),await s();continue}if(h?.state!=="ready"||h.ticket!==M||h.ownerRecord===null||!ke(h.ownerRecord,N))throw new Error(`Process lock claim disappeared or changed before acquisition: ${l}`);const w=firstElectionBlocker(b.claims,h);if(w===null){H=!0;const v=E;return{claim:{claimDirectory:l,intact:()=>y(d,m)&&y(l,v)},release:async()=>{try{await rt(l,d,m,N,M)}catch(Ne){throw F.add(l),Ne}}}}if(Ye(w,N))throw new Ve(e,w);w.claimDirectory!==B&&(B=w.claimDirectory,P?.(),P=_e(()=>He(e,w,performance.now()-$))),O(e,w,S,r),await s()}}finally{if(P?.(),!_)E!==null&&y(I,E)&&i.rmSync(I,{force:!0,recursive:!0});else if(!H&&R!==null&&E!==null){const m=R,T=E;await pe(l,d,()=>y(d,m)&&y(l,T)).catch($=>{throw F.add(l),$})&&c.delete(l)}}}function Ye(e,t){const r=e.ownerRecord;return r!==null&&r.hostname===t.hostname&&r.pid===t.pid&&Q(r.processIdentity,t.processIdentity)&&F.has(e.claimDirectory)}function He(e,t,r){const n=t.ownerRecord;return`Waiting ${ge(r)} for process lock ${a.basename(e)}, `+(n===null?"held by a claim it can't read":`held by pid ${n.pid.toString()} on ${n.hostname} since ${n.createdAt}`)+z(t.claimDirectory)}function C(e,t=process.platform){return t==="win32"&&Z(e)&&typeof e.code=="string"&&ve.has(e.code)}export function tolerateTransientClaimFailure(e,t,r,n=Date.now(),o=process.platform){if(!C(r,o))throw r;const s=e.get(t),c={count:(s?.count??0)+1,firstAtMs:s?.firstAtMs??n};if(c.count>=We&&n-c.firstAtMs>=De)throw r;e.set(t,c)}export function transientWindowsLockRetryDelayMs(e,t,r=process.platform){return!C(e,r)||t>=xe?null:Math.min(se,10*t)}async function A(e,t,r=""){for(let n=1;;n+=1)try{return e()}catch(o){const s=transientWindowsLockRetryDelayMs(o,n);if(s===null)throw o;L.hasSubscribers&&L.publish({metric:"locks.transientWindowsRetries",amount:1});try{await G(s,void 0,{signal:t})}catch(c){throw g(t,r),c}}}function ue(){return{entryReads:new Map,retirements:new Map}}function Xe(e,t){i.mkdirSync(e,{mode:448});try{i.writeFileSync(a.join(e,ne),`${JSON.stringify(t)}
|
|
2
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),i.writeFileSync(a.join(e,U),`${t.token}
|
|
3
|
+
`,{encoding:"utf8",flag:"wx",mode:384})}catch(r){throw i.rmSync(e,{force:!0,recursive:!0}),r}}function Be(e,t){i.writeFileSync(a.join(e,oe),`${t.toString()}
|
|
4
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),i.rmSync(a.join(e,U))}export function nextProcessLockTicket(e){if(e.some(r=>r.state==="changing"))return null;const t=e.reduce((r,n)=>n.ticket===null?r:Math.max(r,n.ticket),0);if(t>=Number.MAX_SAFE_INTEGER)throw new Error("Process lock ticket space is exhausted");return t+1}export function firstElectionBlocker(e,t){if(t.ticket===null||t.ownerRecord===null)return t;const r=t.ownerRecord.token;for(const n of e){if(n.claimDirectory===t.claimDirectory)continue;if(n.state!=="ready"||n.ticket===null||n.ownerRecord===null)return n;const o=n.ownerRecord.token;if(Ge(n.ticket,o,t.ticket,r)<0)return n}return null}function Ge(e,t,r,n){return e===r?t.localeCompare(n):e-r}function le(e,t=null){const r=Oe(e);if(r!=="real")return{state:r};if(t!==null&&!y(e,t))return{state:"changed"};try{return{entries:i.readdirSync(e,{withFileTypes:!0}),state:"listed"}}catch(n){if(u(n,"ENOENT"))return{state:"absent"};throw n}}function fe(e,t,r,n,o){if(t.state!=="listed")return t.state==="absent"?{claims:[],rootAvailable:!0}:t.state==="unsafe"&&tt(e,r,o)?{claims:[],rootAvailable:!0}:{claims:[me(e)],rootAvailable:!1};const{entries:s}=t,c=[];for(const k of s){const f=a.join(e,k.name);let p;try{p=Je(k,f)}catch(S){tolerateTransientClaimFailure(n.entryReads,f,S),c.push(he(f));continue}n.entryReads.delete(f),p===null?n.retirements.delete(f):ze(p,r,o)?et(e,f,p.identity,r,n.retirements)==="held"&&c.push(he(f)):(n.retirements.delete(f),c.push(p.claim))}return{claims:c,rootAvailable:!0}}function Je(e,t){const r=K(t);if(r===null)return null;const n=!e.name.startsWith(x)||!e.isDirectory()?me(t):ye(t),o=K(t);return o===null?null:{claim:n,identity:de(r),modifiedAtMs:Number(o.mtimeMs)}}function Qe(e){const t=K(e);return t===null?null:de(t)}function K(e){try{return i.lstatSync(e,{bigint:!0})}catch(t){if(u(t,"ENOENT"))return null;throw t}}function de(e){return{birthtimeNs:e.birthtimeNs,dev:e.dev,ino:e.ino}}function me(e){return{claimDirectory:e,ownerRecord:null,state:"malformed",ticket:null}}function he(e){return{claimDirectory:e,ownerRecord:null,state:"changing",ticket:null}}function ye(e){const t=st(e),r=Y(a.join(e,U)),n=Ze(e),o=a.basename(e).slice(x.length),s=t===null||t.token===o;return{claimDirectory:e,ownerRecord:t,state:t===null||!s?"malformed":r?"choosing":n===null?"malformed":"ready",ticket:n}}function Ze(e){const t=we(a.join(e,oe));if(t===null)return null;const r=Number(t.trim());return Number.isSafeInteger(r)&&r>0?r:null}function we(e){try{return i.readFileSync(e,"utf8")}catch(t){if(u(t,"ENOENT")||u(t,"EISDIR"))return null;throw t}}function ze({claim:e,modifiedAtMs:t},r,n){const o=e.ownerRecord;if(o===null||o.hostname!==ce)return n.hostScope==="current-host"&&Date.now()-t>=ie;if(Le(o.pid)==="absent")return!0;const s=q(o),c=r.get(e.claimDirectory);if(c?.ownerKey===s&&Date.now()-c.checkedAtMs<Ke)return!1;const k=J(o.pid);return r.set(e.claimDirectory,{checkedAtMs:Date.now(),ownerKey:s}),k!==null&&!Q(k,o.processIdentity)}function et(e,t,r,n,o){n.delete(t);const s=`${e}.reclaiming-${D()}`;try{if(process.platform==="win32"){if(Te(t,s,r)==="absent")return o.delete(t),"removed"}else i.renameSync(t,s)}catch(c){return process.platform!=="win32"&&u(c,"ENOENT")?(o.delete(t),"removed"):(tolerateTransientClaimFailure(o,t,c),"held")}if(o.delete(t),!re(Qe(s),r))throw new Error(`Process lock claim ${t} changed before reclamation and is now at ${s}`);return i.rmSync(s,{maxRetries:Ue,recursive:!0,retryDelay:je}),L.hasSubscribers&&L.publish({metric:"locks.reclaimedClaims",amount:1}),"removed"}function tt(e,t,r){if(r.hostScope!=="current-host")return!1;const n=Ee(e);if(n==="absent")return!0;if(n==="real-directory"||ot(n)<ie)return!1;const o=Ee(e);if(o==="absent")return!0;if(o==="real-directory"||!nt(o,n))return!1;try{return i.unlinkSync(e),t.delete(e),!0}catch(s){if(u(s,"ENOENT"))return!0;if(u(s,"EISDIR")||u(s,"EPERM"))return!1;throw s}}async function rt(e,t,r,n,o){await pe(e,t,()=>{if(!y(t,r))throw new Error(`Process lock directory changed before release: ${t}`);const s=ye(e);if(s.state!=="ready"||s.ticket!==o||s.ownerRecord===null||!ke(s.ownerRecord,n))throw new Error(`Process lock ownership changed before release: ${e}`);return!0})}async function pe(e,t,r){if(process.platform!=="win32")return r()?(i.rmSync(e,{force:!0,recursive:!0}),V(t),!0):!1;const n=`${t}.releasing-${D()}`;return await A(()=>r()?(i.renameSync(e,n),!0):!1)?(await A(()=>{i.rmSync(n,{force:!0,recursive:!0})}),await A(()=>{V(t)}),!0):!1}function Ee(e){try{const t=i.lstatSync(e,{bigint:!0});return t.isDirectory()&&!t.isSymbolicLink()?"real-directory":{birthtimeNs:t.birthtimeNs,ctimeNs:t.ctimeNs,dev:t.dev,ino:t.ino,mode:t.mode,mtimeNs:t.mtimeNs,size:t.size}}catch(t){if(u(t,"ENOENT"))return"absent";throw t}}function nt(e,t){return e.birthtimeNs===t.birthtimeNs&&e.ctimeNs===t.ctimeNs&&e.dev===t.dev&&e.ino===t.ino&&e.mode===t.mode&&e.mtimeNs===t.mtimeNs&&e.size===t.size}function ot(e){return Math.max(0,Date.now()-Number(e.mtimeNs)/1e6)}function V(e){try{i.rmdirSync(e)}catch(t){if(!u(t,"ENOENT")&&!u(t,"ENOTEMPTY")&&!u(t,"EEXIST"))throw t}}function st(e){const t=we(a.join(e,ne));if(t===null)return null;let r;try{r=JSON.parse(t)}catch{return null}return Z(r)?it(r):null}function it(e){const t=Object.keys(e).sort(),r=["createdAt","hostname","pid","processIdentity","schemaVersion","token"];return t.length!==r.length||t.some((n,o)=>n!==r[o])||e.schemaVersion!==W||!ht(e.createdAt)||typeof e.hostname!="string"||e.hostname.length===0||!yt(e.pid)||typeof e.processIdentity!="string"||e.processIdentity.length===0||typeof e.token!="string"||e.token.length===0?null:{createdAt:e.createdAt,hostname:e.hostname,pid:e.pid,processIdentity:e.processIdentity,schemaVersion:W,token:e.token}}function ke(e,t){return q(e)===q(t)}function q(e){return[e.hostname,e.pid.toString(),e.processIdentity,e.token,e.createdAt].join("\0")}function Se(e){return`${e}.dir`}function be(e){const t=a.resolve(ct(e)),r=i.realpathSync.native(a.dirname(t));return a.join(r,a.basename(t))}function ct(e){if(e.trim().length===0)throw new Error("Process lock path must not be empty");return e}function at(e){if(j.getStore()?.has(e))throw new Error(`Reentrant process lock acquisition is not allowed: ${e}`)}function O(e,t,r,n){if(n!==null&&Date.now()-r>=n)throw new ae(e,t)}async function ut(e,t,r){g(t,r),L.hasSubscribers&&L.publish({metric:"locks.contentionRetries",amount:1});try{await G(e,void 0,{signal:t})}catch(n){throw g(t,r),n}}function g(e,t){if(e?.aborted)throw lt(e,t)}function lt(e,t){return e.reason instanceof Error?e.reason:new Error(`Waiting for process lock was aborted: ${t}`)}function ft(e){return e===null?"":` (host=${e.hostname} pid=${e.pid.toString()} identity=${e.processIdentity} createdAt=${e.createdAt})`}function dt(e,t,r){const n=e===void 0?t:e;if(n!==null&&(!Number.isSafeInteger(n)||n<0))throw new Error(`${r} must be null or a non-negative safe integer`);return n}function mt(e,t,r){const n=e??t;if(!Number.isSafeInteger(n)||n<=0)throw new Error(`${r} must be a positive safe integer`);return n}function ht(e){return typeof e=="string"&&e.length>0&&Number.isFinite(Date.parse(e))}function yt(e){return Number.isSafeInteger(e)&&Number(e)>0}function Y(e){try{return i.lstatSync(e),!0}catch(t){if(u(t,"ENOENT"))return!1;throw t}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{execFileSync as
|
|
1
|
+
import{execFileSync as f}from"node:child_process";import c from"node:fs";import{DARWIN_PS_EXECUTABLE as m,HOST_POSIX_INSPECTION_ENVIRONMENT as p,requireWindowsHostPowerShellCommand as I}from"./host-inspection-command.js";import{formatWindowsKernelProcessIdentity as w,parseWindowsKernelProcessIdentity as S}from"./windows-process-identity.js";import{windowsOwnerExecutable as T}from"./windows-native.js";import{hasErrorCode as a}from"../kernel/error-serialization.js";const E=3e3,y=16*1024,x=8e3,P="/proc/sys/kernel/random/boot_id",d=/^linux-proc-start:(\d+)(?:@([\da-f-]+))?$/u;let s,o;export function captureProcessCreationIdentity(e){const t=Number(e);if(!Number.isSafeInteger(t)||t<=0)return null;if(t===process.pid&&s!==void 0)return s;try{let r=null;return process.platform==="linux"?r=N(t):process.platform==="darwin"?r=b(t):process.platform==="win32"&&(r=g(t)),t===process.pid&&r!==null&&(s=r),r}catch{return null}}export function processCreationIdentityMatches(e,t){return observeProcessCreationIdentity(e,t)==="matches"}export function observeProcessCreationIdentity(e,t,r={}){const n=Number(e);if(!Number.isSafeInteger(n)||n<=0||typeof t!="string"||t.length===0)return"unknown";const i=(r.captureIdentity??captureProcessCreationIdentity)(n);return i!==null?sameProcessCreationIdentity(i,t)?"matches":"different":(r.inspectLiveness??inspectProcessLiveness)(n)==="absent"?"different":"unknown"}export function parseWindowsProcessCreationIdentity(e){return S(e)}export function sameProcessCreationIdentity(e,t){if(e===t)return!0;const r=d.exec(e),n=d.exec(t);return r===null||n===null||r[1]!==n[1]?!1:!e.includes("@")||!t.includes("@")}function N(e){const t=parseLinuxProcessCreationIdentity(e,c.readFileSync(`/proc/${e.toString()}/stat`,"utf8")),r=_();return r===null?t:`${t}@${r}`}function _(){if(o!==void 0)return o;try{const e=c.readFileSync(P,"utf8").trim().toLowerCase();o=/^[\da-f-]+$/u.test(e)?e:null}catch{o=null}return o}export function parseLinuxProcessCreationIdentity(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new Error("Linux process stat identity requires a positive pid");const r=t.trim(),n=r.lastIndexOf(")"),i=r.indexOf(" ");if(n<0||i<1||Number(r.slice(0,i))!==e)throw new Error("Linux process stat identity is malformed");const u=r.slice(n+1).trim().split(/\s+/u)[19];if(!/^\d+$/u.test(u))throw new Error("Linux process stat start time is malformed");return`linux-proc-start:${u}`}function b(e){const t=runBoundedProcessIdentityQuery({args:["-p",e.toString(),"-o","pid=,lstart="],environment:p,executable:m,timeoutMs:E,windowsHide:!1});return parseDarwinProcessCreationIdentity(e,t)}export function parseDarwinProcessCreationIdentity(e,t){if(!Number.isSafeInteger(e)||e<=0)throw new Error("Darwin process start identity requires a positive pid");const r=t.trim().replace(/\s+/gu," "),n=/^(\d+) ((?:Sun|Mon|Tue|Wed|Thu|Fri|Sat) (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (?:[1-9]|[12]\d|3[01]) (?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d \d{4})$/u.exec(r);if(n===null||Number(n[1])!==e)throw new Error("Darwin process start identity is malformed");return`darwin-ps-start:${n[2]}`}function g(e){const t=runBoundedProcessIdentityQuery({args:["process-identity",e.toString()],environment:I().environment,executable:T(),timeoutMs:x,windowsHide:!0});if(!/^\d+$/u.test(t))throw new Error("Windows process creation identity is malformed");return w(t)}export function windowsProcessCreationIdentityScript(e){if(!Number.isSafeInteger(e)||e<=0)throw new Error("Windows process creation identity script requires a positive pid");return`$ErrorActionPreference = "Stop"; $p = [Diagnostics.Process]::GetProcessById(${e.toString()}); try { $fileTime = [Int64]$p.StartTime.ToUniversalTime().ToFileTimeUtc(); if ($fileTime -le 0) { exit 3 }; [Console]::Write($fileTime.ToString([Globalization.CultureInfo]::InvariantCulture)) } finally { $p.Dispose() }`}export function runBoundedProcessIdentityQuery(e){if(!Number.isSafeInteger(e.timeoutMs)||e.timeoutMs<=0)throw new Error("Process identity query timeout must be a positive safe integer in milliseconds");return f(e.executable,[...e.args],{encoding:"utf8",env:e.environment,killSignal:"SIGKILL",maxBuffer:y,stdio:["ignore","pipe","ignore"],timeout:e.timeoutMs,windowsHide:e.windowsHide}).trim()}export function inspectProcessLiveness(e){try{return process.kill(e,0),"alive"}catch(t){return a(t,"ESRCH")?"absent":a(t,"EPERM")?"alive":"unknown"}}
|