sneakoscope 6.4.0 → 6.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -34
- package/config/codex-releases/{rust-v0.144.1.json → rust-v0.144.5.json} +5 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/install.js +1 -1
- package/dist/cli/command-manifest-lite.js +2 -3
- package/dist/cli/command-registry.js +6 -4
- package/dist/cli/help-fast.js +0 -1
- package/dist/cli/router.js +24 -3
- package/dist/commands/zellij.js +18 -29
- package/dist/config/skills-manifest.json +62 -62
- package/dist/core/agent-bridge/agent-manifest.js +22 -1
- package/dist/core/agents/agent-codex-cockpit.js +1 -81
- package/dist/core/agents/agent-effort-policy.js +13 -7
- package/dist/core/agents/agent-orchestrator.js +0 -6
- package/dist/core/agents/agent-output-validator.js +2 -1
- package/dist/core/agents/agent-patch-queue-store.js +0 -8
- package/dist/core/agents/agent-proof-evidence.js +0 -6
- package/dist/core/agents/agent-worker-pipeline.js +12 -6
- package/dist/core/agents/native-cli-worker-runtime.js +1 -16
- package/dist/core/agents/native-worker-backend-router.js +1 -1
- package/dist/core/bench.js +1 -1
- package/dist/core/codex/official-goal-mode.js +4 -2
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +11 -17
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +34 -6
- package/dist/core/codex-app/menubar/constants.js +0 -1
- package/dist/core/codex-app.js +1 -1
- package/dist/core/codex-compat/codex-release-manifest.js +5 -5
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +1 -1
- package/dist/core/codex-control/codex-0139-web-search-probe.js +1 -1
- package/dist/core/codex-control/codex-control-proof.js +1 -0
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +1 -1
- package/dist/core/codex-control/codex-lb-launch-recovery.js +7 -3
- package/dist/core/codex-control/codex-sdk-adapter.js +8 -7
- package/dist/core/codex-control/codex-sdk-config-policy.js +4 -24
- package/dist/core/codex-control/codex-sdk-env-policy.js +396 -11
- package/dist/core/codex-control/codex-task-runner.js +112 -57
- package/dist/core/codex-control/gpt-final-arbiter.js +1 -2
- package/dist/core/codex-control/python-codex-sdk-adapter.js +38 -15
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +3 -3
- package/dist/core/codex-native/core-skill-manifest.js +4 -7
- package/dist/core/codex-runtime/resolve-codex-runtime.js +199 -0
- package/dist/core/commands/agent-bridge-command.js +46 -15
- package/dist/core/commands/basic-cli.js +1 -1
- package/dist/core/commands/command-utils.js +2 -2
- package/dist/core/commands/eval-command.js +19 -2
- package/dist/core/commands/goal-command.js +37 -86
- package/dist/core/commands/mad-sks-command.js +0 -2
- package/dist/core/commands/naruto-command.js +236 -176
- package/dist/core/doctor/current-project-guidance.js +1 -1
- package/dist/core/doctor/doctor-dirty-planner.js +1 -1
- package/dist/core/doctor/retired-managed-residue-missions.js +26 -11
- package/dist/core/doctor/retired-managed-residue-private.js +1 -1
- package/dist/core/doctor/retired-managed-residue-runtime.js +12 -2
- package/dist/core/doctor/retired-managed-residue-state.js +7 -7
- package/dist/core/evaluation.js +83 -21
- package/dist/core/feature-fixtures.js +4 -7
- package/dist/core/feature-registry.js +0 -1
- package/dist/core/fsx.js +169 -14
- package/dist/core/goal-workflow.js +71 -140
- package/dist/core/hooks-runtime/hook-io.js +2 -2
- package/dist/core/hooks-runtime.js +228 -50
- package/dist/core/init/skills.js +7 -6
- package/dist/core/init.js +52 -33
- package/dist/core/install/installed-package-smoke.js +1 -1
- package/dist/core/lean-engineering-policy.js +25 -23
- package/dist/core/locks/file-lock.js +74 -21
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/mcp-config/health-check.js +7 -2
- package/dist/core/mission.js +99 -3
- package/dist/core/ops/upgrade-migration-fixtures.js +30 -2
- package/dist/core/pipeline-internals/runtime-core.js +67 -95
- package/dist/core/pipeline-internals/runtime-gates.js +25 -6
- package/dist/core/proof/fake-real-proof-policy.js +32 -9
- package/dist/core/proof/route-proof-gate.js +49 -1
- package/dist/core/provider/model-router.js +2 -0
- package/dist/core/questions.js +31 -5
- package/dist/core/recallpulse.js +2 -2
- package/dist/core/release/canonical-test-proof.js +135 -0
- package/dist/core/release/release-closure-contract.js +1 -0
- package/dist/core/release/release-closure-validation.js +25 -12
- package/dist/core/release/release-closure.js +34 -5
- package/dist/core/release/release-gate-contract.js +4 -3
- package/dist/core/release/release-gate-dag.js +4 -2
- package/dist/core/release/release-pack-content-scanner.js +7 -6
- package/dist/core/release/release-pack-receipt.js +33 -12
- package/dist/core/release/release-real-contract.js +41 -2
- package/dist/core/retention.js +95 -16
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/dollar-manifest-lite.js +1 -1
- package/dist/core/routes.js +18 -20
- package/dist/core/safety/command-contract/contracts.js +33 -0
- package/dist/core/safety/command-contract/types.js +1 -1
- package/dist/core/safety/ssot-guard.js +1 -54
- package/dist/core/stop-gate/stop-gate-check.js +0 -14
- package/dist/core/stop-gate/stop-gate-writer.js +0 -4
- package/dist/core/strategy/adhd-orchestrating-gate.js +2 -2
- package/dist/core/subagents/agent-catalog.js +28 -5
- package/dist/core/subagents/model-policy.js +52 -11
- package/dist/core/subagents/naruto-help-contract.js +2 -1
- package/dist/core/subagents/naruto-proof-projection.js +449 -0
- package/dist/core/subagents/official-subagent-preparation.js +641 -51
- package/dist/core/subagents/official-subagent-prompt.js +16 -6
- package/dist/core/subagents/official-subagent-runner.js +132 -12
- package/dist/core/subagents/subagent-evidence.js +44 -8
- package/dist/core/subagents/wave-lifecycle.js +238 -0
- package/dist/core/update-check.js +13 -4
- package/dist/core/verification/machine-feedback.js +39 -19
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-lane-renderer.js +19 -19
- package/dist/core/zellij/zellij-official-subagent-activity.js +2 -0
- package/dist/core/zellij/zellij-right-column-manager.js +6 -55
- package/dist/core/zellij/zellij-slot-column-anchor.js +4 -5
- package/dist/core/zellij/zellij-slot-pane-renderer.js +1 -1
- package/dist/core/zellij/zellij-ui-mode.js +0 -7
- package/dist/core/zellij/zellij-worker-pane-manager.js +3 -11
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +0 -1
- package/dist/native/sks-menubar/Sources/NotificationCoordinator.swift +1 -3
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +194 -24
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +49 -4
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +38 -10
- package/dist/native/sks-menubar/Sources/StatusItemController.swift +73 -11
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +27 -2
- package/dist/scripts/architecture-guard-check.js +1 -9
- package/dist/scripts/canonical-test-runner.js +51 -8
- package/dist/scripts/check-architecture.js +11 -1
- package/dist/scripts/cli-output-consistency-check.js +0 -2
- package/dist/scripts/codex-0144-app-server-v2-check.js +4 -4
- package/dist/scripts/codex-0144-binary-identity-check.js +10 -4
- package/dist/scripts/codex-0144-capability-check.js +5 -5
- package/dist/scripts/codex-0144-policy-check.js +4 -0
- package/dist/scripts/codex-control-all-pipelines-check.js +2 -1
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +3 -3
- package/dist/scripts/codex-sdk-all-pipelines-check.js +2 -1
- package/dist/scripts/codex-sdk-real-smoke-check.js +20 -2
- package/dist/scripts/current-command-surface-check.js +5 -3
- package/dist/scripts/current-surface-update-e2e-check.js +2 -2
- package/dist/scripts/docs-truthfulness-check.js +8 -6
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +3 -2
- package/dist/scripts/gate-policy-audit-check.js +7 -1
- package/dist/scripts/harness-benchmark-check.js +4 -4
- package/dist/scripts/hook-latency-quantum-check.js +2 -2
- package/dist/scripts/legacy-gate-purge-check.js +4 -2
- package/dist/scripts/loop-directive-check-lib.js +14 -13
- package/dist/scripts/naruto-codex-e2e-check.js +2 -2
- package/dist/scripts/naruto-ssot-gate-aliases-check.js +9 -0
- package/dist/scripts/naruto-ssot-pipeline-default-check.js +10 -0
- package/dist/scripts/naruto-ssot-route-normalization-check.js +8 -0
- package/dist/scripts/naruto-ssot-routing-check.js +12 -0
- package/dist/scripts/product-design-plugin-routing-check.js +4 -9
- package/dist/scripts/release-affected-selector-check.js +7 -1
- package/dist/scripts/release-check-stamp.js +151 -18
- package/dist/scripts/release-dynamic-presets-check.js +5 -2
- package/dist/scripts/release-metadata-1-19-check.js +4 -0
- package/dist/scripts/release-real-check.js +21 -3
- package/dist/scripts/sks-menubar-install-check.js +5 -5
- package/dist/scripts/upgrade-migration-matrix-check.js +278 -5
- package/dist/scripts/zellij-developer-controls-check.js +3 -5
- package/dist/scripts/zellij-initial-main-only-blackbox.js +3 -8
- package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +1 -2
- package/dist/scripts/zellij-right-column-headless-overflow-check.js +1 -1
- package/dist/scripts/zellij-right-column-manager-check.js +3 -4
- package/dist/scripts/zellij-slot-only-ui-check.js +2 -2
- package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +1 -2
- package/docs/demo.tape +1 -1
- package/infra-harness-gates.json +0 -27
- package/package.json +11 -6
- package/release-gates.v2.json +150 -22
- package/schemas/codex/agent-result.schema.json +4 -0
- package/schemas/codex/app-server-0.144/codex_app_server_protocol.v2.schemas.json +1 -18812
- package/schemas/codex/codex-0139-real-probe-result.schema.json +2 -2
- package/schemas/zellij/zellij-right-column-state.schema.json +0 -1
- package/dist/core/commands/ui-command.js +0 -198
- package/dist/core/loops/goal-to-loop-compat.js +0 -22
- package/dist/core/naruto/naruto-allocation-policy.js +0 -98
- package/dist/core/naruto/naruto-finalizer.js +0 -22
- package/dist/core/naruto/naruto-gpt-final-pack.js +0 -50
- package/dist/core/naruto/naruto-real-worker-child.js +0 -209
- package/dist/core/naruto/naruto-real-worker-runtime.js +0 -178
- package/dist/core/naruto/naruto-rebalance-policy.js +0 -47
- package/dist/core/naruto/naruto-verification-pool.js +0 -17
- package/dist/core/ui/dashboard-html.js +0 -110
- package/dist/core/zellij/zellij-dashboard-pane.js +0 -70
- package/dist/core/zellij/zellij-dashboard-renderer.js +0 -59
- package/dist/core/zellij/zellij-naruto-dashboard.js +0 -44
- package/dist/scripts/zellij-dashboard-pane-check.js +0 -69
- package/dist/scripts/zellij-dashboard-watch.js +0 -40
|
@@ -29,15 +29,25 @@ export async function reconcileRetiredGitPolicyMode(root, fix, quarantineRoot, c
|
|
|
29
29
|
const value = await readJson(file, null).catch(() => null);
|
|
30
30
|
if (value?.schema !== 'sks.git-policy.v1')
|
|
31
31
|
return;
|
|
32
|
-
|
|
32
|
+
const mode = String(value.mode || '');
|
|
33
|
+
if (['solo', 'work', 'strict-work', 'ci'].includes(mode))
|
|
33
34
|
return;
|
|
35
|
+
const replacement = mode === 'team'
|
|
36
|
+
? 'work'
|
|
37
|
+
: mode === 'strict-team'
|
|
38
|
+
? 'strict-work'
|
|
39
|
+
: null;
|
|
40
|
+
if (!replacement) {
|
|
41
|
+
await reconcileKnownRetiredPath(root, file, false, fix, quarantineRoot, counters);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
34
44
|
counters.detected += 1;
|
|
35
45
|
if (!fix) {
|
|
36
46
|
counters.remaining += 1;
|
|
37
47
|
return;
|
|
38
48
|
}
|
|
39
49
|
try {
|
|
40
|
-
await writeJsonAtomic(file, { ...value, mode:
|
|
50
|
+
await writeJsonAtomic(file, { ...value, mode: replacement });
|
|
41
51
|
counters.removed += 1;
|
|
42
52
|
counters.rewrittenState += 1;
|
|
43
53
|
}
|
|
@@ -45,7 +45,7 @@ async function reconcileStateFiles(root, fix, quarantineRoot, counters) {
|
|
|
45
45
|
const value = await readJson(file, null).catch(() => null);
|
|
46
46
|
if (!value || typeof value !== 'object')
|
|
47
47
|
continue;
|
|
48
|
-
const stripped = stripRetiredPublicState(value);
|
|
48
|
+
const stripped = stripRetiredPublicState(value, true);
|
|
49
49
|
if (!stripped.changed)
|
|
50
50
|
continue;
|
|
51
51
|
counters.detected += 1;
|
|
@@ -100,12 +100,12 @@ async function reconcileUserStateCollision(root, file, fix, quarantineRoot, coun
|
|
|
100
100
|
counters.remaining += 1;
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
|
-
function stripRetiredPublicState(value) {
|
|
103
|
+
function stripRetiredPublicState(value, routeStateRoot) {
|
|
104
104
|
if (Array.isArray(value)) {
|
|
105
105
|
let changed = false;
|
|
106
106
|
const next = [];
|
|
107
107
|
for (const entry of value) {
|
|
108
|
-
const result = stripRetiredPublicState(entry);
|
|
108
|
+
const result = stripRetiredPublicState(entry, false);
|
|
109
109
|
changed ||= result.changed;
|
|
110
110
|
next.push(result.value);
|
|
111
111
|
}
|
|
@@ -115,16 +115,16 @@ function stripRetiredPublicState(value) {
|
|
|
115
115
|
return { value, changed: false };
|
|
116
116
|
const next = {};
|
|
117
117
|
let changed = false;
|
|
118
|
-
const retiredRoute = isRetiredStateObject(value);
|
|
118
|
+
const retiredRoute = routeStateRoot && isRetiredStateObject(value);
|
|
119
119
|
for (const [key, entry] of Object.entries(value)) {
|
|
120
120
|
if (RETIRED_DB_STATE_KEY_RE.test(key)) {
|
|
121
121
|
changed = true;
|
|
122
122
|
continue;
|
|
123
123
|
}
|
|
124
|
-
if (key === 'preempted_missions' && Array.isArray(entry)) {
|
|
124
|
+
if (routeStateRoot && key === 'preempted_missions' && Array.isArray(entry)) {
|
|
125
125
|
const filtered = entry.filter((row) => !row || typeof row !== 'object' || !isRetiredStateObject(row));
|
|
126
126
|
changed ||= filtered.length !== entry.length;
|
|
127
|
-
const nested = stripRetiredPublicState(filtered);
|
|
127
|
+
const nested = stripRetiredPublicState(filtered, false);
|
|
128
128
|
changed ||= nested.changed;
|
|
129
129
|
next[key] = nested.value;
|
|
130
130
|
continue;
|
|
@@ -137,7 +137,7 @@ function stripRetiredPublicState(value) {
|
|
|
137
137
|
changed = true;
|
|
138
138
|
continue;
|
|
139
139
|
}
|
|
140
|
-
const nested = stripRetiredPublicState(entry);
|
|
140
|
+
const nested = stripRetiredPublicState(entry, false);
|
|
141
141
|
changed ||= nested.changed;
|
|
142
142
|
next[key] = nested.value;
|
|
143
143
|
}
|
package/dist/core/evaluation.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { nowIso, sha256, writeJsonAtomic } from './fsx.js';
|
|
3
|
+
import { DEFAULT_OFFICIAL_SUBAGENT_JOB_MAX_RUNTIME_SECONDS, DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH, DEFAULT_OFFICIAL_SUBAGENT_MAX_THREADS } from './subagents/official-subagent-config.js';
|
|
3
4
|
import { contextCapsule } from './triwiki-attention.js';
|
|
4
5
|
import { validateWikiCoordinateIndex } from './wiki-coordinate.js';
|
|
5
6
|
export const DEFAULT_EVAL_THRESHOLDS = Object.freeze({
|
|
@@ -67,9 +68,9 @@ export const PERMISSION_PROFILES = Object.freeze({
|
|
|
67
68
|
dangerous_full_access: { filesystem: 'full-access', network: 'controlled', purpose: 'Never default. Requires explicit reason and review.' }
|
|
68
69
|
});
|
|
69
70
|
export const DEFAULT_MULTIAGENT_V2 = Object.freeze({
|
|
70
|
-
max_threads:
|
|
71
|
-
max_depth:
|
|
72
|
-
job_max_runtime_seconds:
|
|
71
|
+
max_threads: DEFAULT_OFFICIAL_SUBAGENT_MAX_THREADS,
|
|
72
|
+
max_depth: DEFAULT_OFFICIAL_SUBAGENT_MAX_DEPTH,
|
|
73
|
+
job_max_runtime_seconds: DEFAULT_OFFICIAL_SUBAGENT_JOB_MAX_RUNTIME_SECONDS,
|
|
73
74
|
wait_control: 'bounded_wait_then_structured_summary',
|
|
74
75
|
subagent_output: 'structured_summary_only'
|
|
75
76
|
});
|
|
@@ -88,9 +89,9 @@ export const ZELLIJ_COCKPIT_VIEWS = Object.freeze([
|
|
|
88
89
|
'Code Structure View',
|
|
89
90
|
'Statusline / Terminal Title Preview'
|
|
90
91
|
]);
|
|
91
|
-
export function
|
|
92
|
+
export function serializedSizeBytes(value) {
|
|
92
93
|
const text = typeof value === 'string' ? value : JSON.stringify(value);
|
|
93
|
-
return
|
|
94
|
+
return Buffer.byteLength(String(text ?? ''), 'utf8');
|
|
94
95
|
}
|
|
95
96
|
export function classifyToolError(input = {}) {
|
|
96
97
|
const text = `${input.code || ''} ${input.name || ''} ${input.message || ''} ${input.stderr || ''}`.toLowerCase();
|
|
@@ -472,7 +473,19 @@ function scoreSelection(allClaims, selectedIds) {
|
|
|
472
473
|
accuracy_proxy: Number(accuracy.toFixed(4))
|
|
473
474
|
};
|
|
474
475
|
}
|
|
475
|
-
function
|
|
476
|
+
function tokenMeasurementFromEvidence(evidence, label) {
|
|
477
|
+
const rawCount = evidence?.[`${label}_tokens`];
|
|
478
|
+
const source = String(evidence?.source || '').trim();
|
|
479
|
+
if (rawCount === null || rawCount === undefined || !source) {
|
|
480
|
+
return { token_count: null, token_evidence: null };
|
|
481
|
+
}
|
|
482
|
+
const count = Number(rawCount);
|
|
483
|
+
if (!Number.isInteger(count) || count < 0) {
|
|
484
|
+
return { token_count: null, token_evidence: null };
|
|
485
|
+
}
|
|
486
|
+
return { token_count: count, token_evidence: { source } };
|
|
487
|
+
}
|
|
488
|
+
function metricBlock({ label, context, scenario, msPerRun, tokenMeasurement }) {
|
|
476
489
|
const selectedIds = (context.claims || []).map((claim) => claim.id);
|
|
477
490
|
const wikiValidation = context.wiki ? validateWikiCoordinateIndex(context.wiki) : { ok: false };
|
|
478
491
|
const voxel = context.wiki?.vx || context.wiki?.voxel_overlay || null;
|
|
@@ -480,7 +493,14 @@ function metricBlock({ label, context, scenario, msPerRun }) {
|
|
|
480
493
|
return {
|
|
481
494
|
label,
|
|
482
495
|
context_hash: sha256(JSON.stringify(context)),
|
|
483
|
-
|
|
496
|
+
serialized_size_bytes: serializedSizeBytes(context),
|
|
497
|
+
size_metric: {
|
|
498
|
+
name: 'serialized_json_bytes',
|
|
499
|
+
unit: 'bytes',
|
|
500
|
+
proxy_for_tokens: false
|
|
501
|
+
},
|
|
502
|
+
token_count: tokenMeasurement?.token_count ?? null,
|
|
503
|
+
token_evidence: tokenMeasurement?.token_evidence ?? null,
|
|
484
504
|
context_build_ms_per_run: Number(msPerRun.toFixed(4)),
|
|
485
505
|
wiki: context.wiki ? {
|
|
486
506
|
schema: context.wiki.schema,
|
|
@@ -493,16 +513,40 @@ function metricBlock({ label, context, scenario, msPerRun }) {
|
|
|
493
513
|
quality: scoreSelection(scenario.claims, selectedIds)
|
|
494
514
|
};
|
|
495
515
|
}
|
|
516
|
+
function measuredTokenEvidence(metric) {
|
|
517
|
+
const count = metric?.token_count;
|
|
518
|
+
const identity = String(metric?.token_evidence?.source || '').trim();
|
|
519
|
+
return Number.isInteger(count) && count >= 0 && identity ? { count, identity } : null;
|
|
520
|
+
}
|
|
521
|
+
function serializedSize(metric) {
|
|
522
|
+
const size = metric?.serialized_size_bytes;
|
|
523
|
+
return Number.isFinite(size) && size >= 0 ? Number(size) : null;
|
|
524
|
+
}
|
|
496
525
|
export function compareMetricBlocks(baseline, candidate, thresholds = DEFAULT_EVAL_THRESHOLDS) {
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
526
|
+
const baselineTokenEvidence = measuredTokenEvidence(baseline);
|
|
527
|
+
const candidateTokenEvidence = measuredTokenEvidence(candidate);
|
|
528
|
+
const comparableTokenEvidence = baselineTokenEvidence !== null
|
|
529
|
+
&& baselineTokenEvidence.count > 0
|
|
530
|
+
&& candidateTokenEvidence !== null
|
|
531
|
+
&& baselineTokenEvidence.identity === candidateTokenEvidence.identity
|
|
532
|
+
? { baseline: baselineTokenEvidence.count, candidate: candidateTokenEvidence.count, identity: baselineTokenEvidence.identity }
|
|
533
|
+
: null;
|
|
534
|
+
const tokenEvidenceAvailable = comparableTokenEvidence !== null;
|
|
535
|
+
const tokenSavingsPct = comparableTokenEvidence
|
|
536
|
+
? (comparableTokenEvidence.baseline - comparableTokenEvidence.candidate) / comparableTokenEvidence.baseline
|
|
537
|
+
: null;
|
|
538
|
+
const baselineSize = serializedSize(baseline);
|
|
539
|
+
const candidateSize = serializedSize(candidate);
|
|
540
|
+
const serializedSizeSavingsPct = baselineSize !== null && baselineSize > 0 && candidateSize !== null
|
|
541
|
+
? (baselineSize - candidateSize) / baselineSize
|
|
542
|
+
: null;
|
|
500
543
|
const accuracyDelta = candidate.quality.accuracy_proxy - baseline.quality.accuracy_proxy;
|
|
501
544
|
const precisionDelta = candidate.quality.relevance_precision - baseline.quality.relevance_precision;
|
|
502
545
|
const supportDelta = candidate.quality.support_ratio - baseline.quality.support_ratio;
|
|
503
546
|
const buildRuntimeDeltaMs = candidate.context_build_ms_per_run - baseline.context_build_ms_per_run;
|
|
504
547
|
const checks = {
|
|
505
|
-
|
|
548
|
+
token_evidence: tokenEvidenceAvailable,
|
|
549
|
+
token_savings: tokenSavingsPct === null ? null : tokenSavingsPct >= thresholds.min_token_savings_pct,
|
|
506
550
|
accuracy_delta: accuracyDelta >= thresholds.min_accuracy_delta,
|
|
507
551
|
required_recall: candidate.quality.required_recall >= thresholds.min_required_recall,
|
|
508
552
|
unsupported_critical: candidate.quality.unsupported_critical_selected <= thresholds.max_unsupported_critical_selected,
|
|
@@ -511,13 +555,23 @@ export function compareMetricBlocks(baseline, candidate, thresholds = DEFAULT_EV
|
|
|
511
555
|
if (candidate.wiki)
|
|
512
556
|
checks.wiki_index = candidate.wiki.valid === true;
|
|
513
557
|
return {
|
|
514
|
-
token_savings_pct: Number(tokenSavingsPct.toFixed(4)),
|
|
558
|
+
token_savings_pct: tokenSavingsPct === null ? null : Number(tokenSavingsPct.toFixed(4)),
|
|
559
|
+
serialized_size_savings_pct: serializedSizeSavingsPct === null ? null : Number(serializedSizeSavingsPct.toFixed(4)),
|
|
560
|
+
token_measurement: {
|
|
561
|
+
available: tokenEvidenceAvailable,
|
|
562
|
+
evidence_identity: comparableTokenEvidence?.identity ?? null,
|
|
563
|
+
reason: tokenEvidenceAvailable
|
|
564
|
+
? null
|
|
565
|
+
: baselineTokenEvidence && candidateTokenEvidence && baselineTokenEvidence.identity !== candidateTokenEvidence.identity
|
|
566
|
+
? 'matching_token_evidence_identity_required'
|
|
567
|
+
: 'actual_token_counts_with_evidence_required'
|
|
568
|
+
},
|
|
515
569
|
accuracy_delta: Number(accuracyDelta.toFixed(4)),
|
|
516
570
|
precision_delta: Number(precisionDelta.toFixed(4)),
|
|
517
571
|
support_ratio_delta: Number(supportDelta.toFixed(4)),
|
|
518
572
|
build_runtime_delta_ms: Number(buildRuntimeDeltaMs.toFixed(4)),
|
|
519
573
|
checks,
|
|
520
|
-
meaningful_improvement: Object.values(checks).every(
|
|
574
|
+
meaningful_improvement: Object.values(checks).every((value) => value === true)
|
|
521
575
|
};
|
|
522
576
|
}
|
|
523
577
|
export function runEvaluationBenchmark(opts = {}) {
|
|
@@ -536,17 +590,19 @@ export function runEvaluationBenchmark(opts = {}) {
|
|
|
536
590
|
label: 'uncompressed-all-claims',
|
|
537
591
|
context: baselineTiming.result,
|
|
538
592
|
scenario,
|
|
539
|
-
msPerRun: baselineTiming.ms_per_run
|
|
593
|
+
msPerRun: baselineTiming.ms_per_run,
|
|
594
|
+
tokenMeasurement: tokenMeasurementFromEvidence(opts.tokenEvidence, 'baseline')
|
|
540
595
|
});
|
|
541
596
|
const candidate = metricBlock({
|
|
542
597
|
label: 'triwiki-compressed-capsule',
|
|
543
598
|
context: candidateTiming.result,
|
|
544
599
|
scenario,
|
|
545
|
-
msPerRun: candidateTiming.ms_per_run
|
|
600
|
+
msPerRun: candidateTiming.ms_per_run,
|
|
601
|
+
tokenMeasurement: tokenMeasurementFromEvidence(opts.tokenEvidence, 'candidate')
|
|
546
602
|
});
|
|
547
603
|
const comparison = compareMetricBlocks(baseline, candidate, opts.thresholds || DEFAULT_EVAL_THRESHOLDS);
|
|
548
604
|
return {
|
|
549
|
-
schema_version:
|
|
605
|
+
schema_version: 2,
|
|
550
606
|
generated_at: nowIso(),
|
|
551
607
|
scenario: {
|
|
552
608
|
id: scenario.id,
|
|
@@ -560,25 +616,31 @@ export function runEvaluationBenchmark(opts = {}) {
|
|
|
560
616
|
candidate,
|
|
561
617
|
comparison,
|
|
562
618
|
notes: [
|
|
563
|
-
'
|
|
619
|
+
'serialized_size_bytes is a deterministic UTF-8 JSON byte-size metric, not a token estimate.',
|
|
620
|
+
'Token savings are unavailable unless actual baseline and candidate token counts share the same nonempty token_evidence.source identity.',
|
|
564
621
|
'accuracy_proxy scores evidence-weighted context selection quality; it is not a live model task accuracy measurement.'
|
|
565
622
|
]
|
|
566
623
|
};
|
|
567
624
|
}
|
|
568
625
|
function reportMetric(report) {
|
|
569
|
-
if (report?.candidate?.quality && report
|
|
626
|
+
if (report?.candidate?.quality && hasSizeOrTokenMetric(report.candidate))
|
|
570
627
|
return report.candidate;
|
|
571
|
-
if (report?.metrics?.quality && report
|
|
628
|
+
if (report?.metrics?.quality && hasSizeOrTokenMetric(report.metrics))
|
|
572
629
|
return report.metrics;
|
|
573
|
-
if (report?.quality && report
|
|
630
|
+
if (report?.quality && hasSizeOrTokenMetric(report))
|
|
574
631
|
return report;
|
|
575
632
|
throw new Error('Unsupported eval report shape.');
|
|
576
633
|
}
|
|
634
|
+
function hasSizeOrTokenMetric(metric) {
|
|
635
|
+
return metric?.serialized_size_bytes !== undefined
|
|
636
|
+
|| metric?.token_count !== undefined
|
|
637
|
+
|| metric?.estimated_tokens !== undefined;
|
|
638
|
+
}
|
|
577
639
|
export function compareEvaluationReports(baselineReport, candidateReport, thresholds = DEFAULT_EVAL_THRESHOLDS) {
|
|
578
640
|
const baseline = reportMetric(baselineReport);
|
|
579
641
|
const candidate = reportMetric(candidateReport);
|
|
580
642
|
return {
|
|
581
|
-
schema_version:
|
|
643
|
+
schema_version: 2,
|
|
582
644
|
generated_at: nowIso(),
|
|
583
645
|
baseline_label: baseline.label || baselineReport?.scenario?.id || 'baseline',
|
|
584
646
|
candidate_label: candidate.label || candidateReport?.scenario?.id || 'candidate',
|
|
@@ -40,10 +40,6 @@ const FIXTURES = Object.freeze({
|
|
|
40
40
|
'cli-check': fixture('execute', 'sks check --tier confidence --sla 5m --plan --json', [], 'pass'),
|
|
41
41
|
'cli-plan': fixture('execute', 'sks plan "fixture" --json', [], 'pass'),
|
|
42
42
|
'cli-review': fixture('execute', 'sks review --diff HEAD --json', [], 'pass'),
|
|
43
|
-
'cli-ui': fixture('static', 'sks ui [--port 4477] [--mission latest] [--once] [--json]', [], 'pass', {
|
|
44
|
-
quality: 'static_contract',
|
|
45
|
-
reason: 'UI command opens a localhost dashboard; release fixture tracks the CLI contract without launching a server.'
|
|
46
|
-
}),
|
|
47
43
|
'cli-run': fixture('execute_and_validate_artifacts', 'sks run "fixture" --mock --json', ['run-classification.json', 'completion-proof.json', 'evidence-index.json', 'route-completion-contract.json', 'trust-report.json', 'work-order-ledger.json'], 'blocked', { reason: 'finalizeMockRun() in run-command.ts intentionally hardcodes gate.passed=false for every --mock invocation so a mock run can never claim a real completion; it does write all declared artifacts, including a work-order-ledger honestly closed to blocked (18차).' }),
|
|
48
44
|
'cli-status': fixture('execute', 'sks status --json', [], 'pass'),
|
|
49
45
|
'cli-usage': fixture('execute', 'sks usage overview', [], 'pass'),
|
|
@@ -66,7 +62,7 @@ const FIXTURES = Object.freeze({
|
|
|
66
62
|
'cli-selftest': fixture('execute', 'sks selftest --mock', [], 'pass'),
|
|
67
63
|
'cli-git': fixture('execute', 'sks git policy --json', [], 'pass'),
|
|
68
64
|
'cli-uninstall': fixture('execute', 'sks uninstall --dry-run --json', [], 'pass'),
|
|
69
|
-
'cli-goal': fixture('
|
|
65
|
+
'cli-goal': fixture('execute', 'sks goal create "Fixture smoke: create a minimal Node.js CLI health-check script" --json', [], 'pass', { reason: 'The compatibility command is stateless: it prints a detailed Codex native /goal request and writes no SKS mission, artifact, loop, or fallback state.' }),
|
|
70
66
|
'cli-seo-geo-optimizer': fixture('execute_and_validate_artifacts', 'sks seo-geo-optimizer fixture --mode seo --json', ['search-visibility/site-inventory.json', 'search-visibility/seo-findings.json', 'search-visibility/verification-report.json', 'seo-gate.json', 'completion-proof.json'], 'pass'),
|
|
71
67
|
'cli-research': fixture('execute_and_validate_artifacts', 'sks research run latest --mock --json', ['research-gate.json', 'completion-proof.json'], 'blocked', { timeout_ms: 180000, reason: '"run" (not "status") is the command that actually writes research-gate.json/completion-proof.json, but research is a two-step prepare-then-run workflow gated by an active-route-not-closed check between steps that a single fixture command cannot express; on a hermetic run "latest" will not be a properly prepared+closed research mission.' }),
|
|
72
68
|
'cli-qa-loop': fixture('execute_and_validate_artifacts', 'sks qa-loop run latest --mock --json', ['qa-gate.json', 'completion-proof.json'], 'pass', { timeout_ms: 180000 }),
|
|
@@ -152,8 +148,9 @@ const FIXTURES = Object.freeze({
|
|
|
152
148
|
quality: 'wiring_only',
|
|
153
149
|
reason: 'Policy-only route (answer-only conversational mode with no writes); nothing executable to run beyond static contract text.'
|
|
154
150
|
}),
|
|
155
|
-
'route-goal': fixture('
|
|
156
|
-
|
|
151
|
+
'route-goal': fixture('static', '$Goal Codex-native control route', [], 'pass', {
|
|
152
|
+
quality: 'wiring_only',
|
|
153
|
+
reason: 'Goal lifecycle is owned entirely by Codex native /goal. The SKS surface only builds a detailed native objective and command; it creates no mission, proof artifact, compatibility loop, or fallback goal state.'
|
|
157
154
|
}),
|
|
158
155
|
'route-super-search': fixture('execute', 'sks run "$Super-Search doctor" --execute --json', [], 'pass'),
|
|
159
156
|
'route-seo-geo-optimizer': fixture('execute_and_validate_artifacts', 'sks seo-geo-optimizer fixture --mode geo --json', ['search-visibility/site-inventory.json', 'search-visibility/geo-findings.json', 'search-visibility/verification-report.json', 'geo-gate.json', 'completion-proof.json'], 'pass'),
|
|
@@ -13,7 +13,6 @@ export const FEATURE_INVENTORY_SCHEMA = 'sks.feature-inventory.v1';
|
|
|
13
13
|
export const ALL_FEATURES_SELFTEST_SCHEMA = 'sks.all-features-selftest.v1';
|
|
14
14
|
export const ALL_FEATURE_COMPLETION_SCHEMA = 'sks.all-feature-completion.v1';
|
|
15
15
|
const HANDLER_ALIAS_TO_COMMAND = Object.freeze({
|
|
16
|
-
ui: 'wizard',
|
|
17
16
|
auth: 'codex-lb',
|
|
18
17
|
hook: 'hooks',
|
|
19
18
|
memory: 'gc',
|
package/dist/core/fsx.js
CHANGED
|
@@ -446,6 +446,88 @@ export class TailBuffer {
|
|
|
446
446
|
return this.totalBytes;
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
|
+
const activeDetachedProcessGroups = new Map();
|
|
450
|
+
let processGroupLifecycleHandlersInstalled = false;
|
|
451
|
+
let relayingParentSignal = false;
|
|
452
|
+
export function registerDetachedProcessGroup(child) {
|
|
453
|
+
const pid = child.pid;
|
|
454
|
+
if (process.platform === 'win32' || !pid)
|
|
455
|
+
return () => { };
|
|
456
|
+
const group = { pid, child };
|
|
457
|
+
activeDetachedProcessGroups.set(pid, group);
|
|
458
|
+
installProcessGroupLifecycleHandlers();
|
|
459
|
+
return () => {
|
|
460
|
+
if (activeDetachedProcessGroups.get(pid) !== group)
|
|
461
|
+
return;
|
|
462
|
+
activeDetachedProcessGroups.delete(pid);
|
|
463
|
+
if (activeDetachedProcessGroups.size === 0)
|
|
464
|
+
uninstallProcessGroupLifecycleHandlers();
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
function installProcessGroupLifecycleHandlers() {
|
|
468
|
+
if (processGroupLifecycleHandlersInstalled || process.platform === 'win32')
|
|
469
|
+
return;
|
|
470
|
+
processGroupLifecycleHandlersInstalled = true;
|
|
471
|
+
process.on('exit', terminateRegisteredProcessGroups);
|
|
472
|
+
// Run before existing once listeners remove themselves so rawListeners still
|
|
473
|
+
// reflects whether Node's default signal termination was already suppressed.
|
|
474
|
+
process.prependListener('SIGHUP', handleParentSighup);
|
|
475
|
+
process.prependListener('SIGINT', handleParentSigint);
|
|
476
|
+
process.prependListener('SIGTERM', handleParentSigterm);
|
|
477
|
+
}
|
|
478
|
+
function uninstallProcessGroupLifecycleHandlers() {
|
|
479
|
+
if (!processGroupLifecycleHandlersInstalled)
|
|
480
|
+
return;
|
|
481
|
+
processGroupLifecycleHandlersInstalled = false;
|
|
482
|
+
process.off('exit', terminateRegisteredProcessGroups);
|
|
483
|
+
process.off('SIGHUP', handleParentSighup);
|
|
484
|
+
process.off('SIGINT', handleParentSigint);
|
|
485
|
+
process.off('SIGTERM', handleParentSigterm);
|
|
486
|
+
}
|
|
487
|
+
function handleParentSighup() {
|
|
488
|
+
relayParentSignal('SIGHUP', handleParentSighup);
|
|
489
|
+
}
|
|
490
|
+
function handleParentSigint() {
|
|
491
|
+
relayParentSignal('SIGINT', handleParentSigint);
|
|
492
|
+
}
|
|
493
|
+
function handleParentSigterm() {
|
|
494
|
+
relayParentSignal('SIGTERM', handleParentSigterm);
|
|
495
|
+
}
|
|
496
|
+
function relayParentSignal(signal, ownHandler) {
|
|
497
|
+
if (relayingParentSignal)
|
|
498
|
+
return;
|
|
499
|
+
terminateRegisteredProcessGroups();
|
|
500
|
+
if (process.rawListeners(signal).some((listener) => listener !== ownHandler))
|
|
501
|
+
return;
|
|
502
|
+
relayingParentSignal = true;
|
|
503
|
+
uninstallProcessGroupLifecycleHandlers();
|
|
504
|
+
try {
|
|
505
|
+
process.kill(process.pid, signal);
|
|
506
|
+
}
|
|
507
|
+
catch {
|
|
508
|
+
process.exit(signal === 'SIGHUP' ? 129 : signal === 'SIGINT' ? 130 : 143);
|
|
509
|
+
}
|
|
510
|
+
setImmediate(() => {
|
|
511
|
+
relayingParentSignal = false;
|
|
512
|
+
if (activeDetachedProcessGroups.size > 0)
|
|
513
|
+
installProcessGroupLifecycleHandlers();
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
function terminateRegisteredProcessGroups() {
|
|
517
|
+
for (const group of [...activeDetachedProcessGroups.values()]) {
|
|
518
|
+
if (activeDetachedProcessGroups.get(group.pid) !== group)
|
|
519
|
+
continue;
|
|
520
|
+
try {
|
|
521
|
+
process.kill(-group.pid, 'SIGKILL');
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
catch { }
|
|
525
|
+
try {
|
|
526
|
+
group.child.kill('SIGKILL');
|
|
527
|
+
}
|
|
528
|
+
catch { }
|
|
529
|
+
}
|
|
530
|
+
}
|
|
449
531
|
export function runProcess(command, args, options = {}) {
|
|
450
532
|
return new Promise((resolve) => {
|
|
451
533
|
const tailBytes = options.maxOutputBytes ?? DEFAULT_PROCESS_TAIL_BYTES;
|
|
@@ -453,26 +535,36 @@ export function runProcess(command, args, options = {}) {
|
|
|
453
535
|
const stderrTail = new TailBuffer(tailBytes);
|
|
454
536
|
const timeoutMs = options.timeoutMs ?? DEFAULT_PROCESS_TIMEOUT_MS;
|
|
455
537
|
let killedByTimeout = false;
|
|
538
|
+
let spawnRegistrationFailed = false;
|
|
456
539
|
let settled = false;
|
|
540
|
+
let processTreeCleanup = null;
|
|
457
541
|
let stdoutStream = null;
|
|
458
542
|
let stderrStream = null;
|
|
459
543
|
const spawnOptions = {
|
|
460
544
|
cwd: options.cwd || process.cwd(),
|
|
461
545
|
shell: false,
|
|
462
546
|
stdio: [options.input !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],
|
|
547
|
+
detached: process.platform !== 'win32',
|
|
463
548
|
};
|
|
464
|
-
if (options.
|
|
549
|
+
if (options.envMode === 'replace') {
|
|
550
|
+
spawnOptions.env = { ...(options.env || {}) };
|
|
551
|
+
}
|
|
552
|
+
else if (options.env) {
|
|
465
553
|
spawnOptions.env = { ...process.env, ...options.env };
|
|
466
554
|
}
|
|
467
555
|
const child = spawn(command, args, spawnOptions);
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
556
|
+
const unregisterDetachedProcessGroup = registerDetachedProcessGroup(child);
|
|
557
|
+
const pausedForSpawnRegistration = Boolean(options.onSpawn
|
|
558
|
+
&& child.pid
|
|
559
|
+
&& process.platform !== 'win32'
|
|
560
|
+
&& child.kill('SIGSTOP'));
|
|
471
561
|
const finish = async (result) => {
|
|
472
562
|
if (settled)
|
|
473
563
|
return;
|
|
474
564
|
settled = true;
|
|
475
565
|
clearTimeout(timer);
|
|
566
|
+
await processTreeCleanup;
|
|
567
|
+
unregisterDetachedProcessGroup();
|
|
476
568
|
try {
|
|
477
569
|
await stdoutStream?.end?.();
|
|
478
570
|
}
|
|
@@ -493,16 +585,7 @@ export function runProcess(command, args, options = {}) {
|
|
|
493
585
|
}
|
|
494
586
|
const timer = setTimeout(() => {
|
|
495
587
|
killedByTimeout = true;
|
|
496
|
-
|
|
497
|
-
child.kill('SIGTERM');
|
|
498
|
-
}
|
|
499
|
-
catch { }
|
|
500
|
-
setTimeout(() => {
|
|
501
|
-
try {
|
|
502
|
-
child.kill('SIGKILL');
|
|
503
|
-
}
|
|
504
|
-
catch { }
|
|
505
|
-
}, 1500).unref?.();
|
|
588
|
+
processTreeCleanup = terminateProcessTree(child.pid, child);
|
|
506
589
|
}, timeoutMs);
|
|
507
590
|
timer.unref?.();
|
|
508
591
|
child.stdout?.on('data', (d) => {
|
|
@@ -524,6 +607,7 @@ export function runProcess(command, args, options = {}) {
|
|
|
524
607
|
stderrBytes: stderrTail.totalBytesCounted,
|
|
525
608
|
truncated: stdoutTail.truncated || stderrTail.truncated,
|
|
526
609
|
timedOut: killedByTimeout,
|
|
610
|
+
...(spawnRegistrationFailed ? { spawnRegistrationFailed: true } : {}),
|
|
527
611
|
}));
|
|
528
612
|
child.on('close', (code) => void finish({
|
|
529
613
|
code: killedByTimeout ? 124 : code,
|
|
@@ -534,9 +618,80 @@ export function runProcess(command, args, options = {}) {
|
|
|
534
618
|
stderrBytes: stderrTail.totalBytesCounted,
|
|
535
619
|
truncated: stdoutTail.truncated || stderrTail.truncated,
|
|
536
620
|
timedOut: killedByTimeout,
|
|
621
|
+
...(spawnRegistrationFailed ? { spawnRegistrationFailed: true } : {}),
|
|
537
622
|
}));
|
|
623
|
+
void (async () => {
|
|
624
|
+
if (options.onSpawn) {
|
|
625
|
+
const pid = child.pid;
|
|
626
|
+
if (!pid) {
|
|
627
|
+
spawnRegistrationFailed = true;
|
|
628
|
+
child.kill('SIGKILL');
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
try {
|
|
632
|
+
await options.onSpawn(pid);
|
|
633
|
+
}
|
|
634
|
+
catch {
|
|
635
|
+
spawnRegistrationFailed = true;
|
|
636
|
+
processTreeCleanup = terminateProcessTree(pid, child);
|
|
637
|
+
await processTreeCleanup;
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
if (pausedForSpawnRegistration)
|
|
641
|
+
child.kill('SIGCONT');
|
|
642
|
+
}
|
|
643
|
+
if (options.input !== undefined && child.stdin)
|
|
644
|
+
child.stdin.end(options.input);
|
|
645
|
+
})();
|
|
538
646
|
});
|
|
539
647
|
}
|
|
648
|
+
async function terminateProcessTree(pid, child) {
|
|
649
|
+
signalProcessTree(pid, 'SIGTERM', child);
|
|
650
|
+
if (await waitForProcessTreeExit(pid, 1_000))
|
|
651
|
+
return;
|
|
652
|
+
signalProcessTree(pid, 'SIGKILL', child);
|
|
653
|
+
await waitForProcessTreeExit(pid, 1_500);
|
|
654
|
+
}
|
|
655
|
+
function signalProcessTree(pid, signal, child) {
|
|
656
|
+
if (pid && process.platform !== 'win32') {
|
|
657
|
+
try {
|
|
658
|
+
process.kill(-pid, signal);
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
catch { }
|
|
662
|
+
}
|
|
663
|
+
try {
|
|
664
|
+
child.kill(signal);
|
|
665
|
+
}
|
|
666
|
+
catch { }
|
|
667
|
+
}
|
|
668
|
+
async function waitForProcessTreeExit(pid, timeoutMs) {
|
|
669
|
+
if (!pid)
|
|
670
|
+
return true;
|
|
671
|
+
const deadline = Date.now() + timeoutMs;
|
|
672
|
+
while (Date.now() < deadline) {
|
|
673
|
+
if (!processTreeIsAlive(pid))
|
|
674
|
+
return true;
|
|
675
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
676
|
+
}
|
|
677
|
+
return !processTreeIsAlive(pid);
|
|
678
|
+
}
|
|
679
|
+
function processTreeIsAlive(pid) {
|
|
680
|
+
if (process.platform !== 'win32') {
|
|
681
|
+
try {
|
|
682
|
+
process.kill(-pid, 0);
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
catch { }
|
|
686
|
+
}
|
|
687
|
+
try {
|
|
688
|
+
process.kill(pid, 0);
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
catch {
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
540
695
|
export async function readStdin() {
|
|
541
696
|
let data = '';
|
|
542
697
|
process.stdin.setEncoding('utf8');
|