@descryy/runtime-orchestrator 0.0.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/dist/attach-to-running-jvm-process.d.ts +139 -0
- package/dist/attach-to-running-jvm-process.d.ts.map +1 -0
- package/dist/attach-to-running-jvm-process.js +338 -0
- package/dist/attach-to-running-jvm-process.js.map +1 -0
- package/dist/attach-to-running-node-process.d.ts +138 -0
- package/dist/attach-to-running-node-process.d.ts.map +1 -0
- package/dist/attach-to-running-node-process.js +315 -0
- package/dist/attach-to-running-node-process.js.map +1 -0
- package/dist/attach-to-running-process.d.ts +70 -0
- package/dist/attach-to-running-process.d.ts.map +1 -0
- package/dist/attach-to-running-process.js +90 -0
- package/dist/attach-to-running-process.js.map +1 -0
- package/dist/cdp-client.d.ts +37 -0
- package/dist/cdp-client.d.ts.map +1 -0
- package/dist/cdp-client.js +111 -0
- package/dist/cdp-client.js.map +1 -0
- package/dist/cgroup-partial-restriction.d.ts +127 -0
- package/dist/cgroup-partial-restriction.d.ts.map +1 -0
- package/dist/cgroup-partial-restriction.js +236 -0
- package/dist/cgroup-partial-restriction.js.map +1 -0
- package/dist/collector-version.d.ts +12 -0
- package/dist/collector-version.d.ts.map +1 -0
- package/dist/collector-version.js +14 -0
- package/dist/collector-version.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumented-execution.d.ts +111 -0
- package/dist/instrumented-execution.d.ts.map +1 -0
- package/dist/instrumented-execution.js +363 -0
- package/dist/instrumented-execution.js.map +1 -0
- package/dist/jvm-agent/build.d.ts +72 -0
- package/dist/jvm-agent/build.d.ts.map +1 -0
- package/dist/jvm-agent/build.js +156 -0
- package/dist/jvm-agent/build.js.map +1 -0
- package/dist/polling-output-source.d.ts +28 -0
- package/dist/polling-output-source.d.ts.map +1 -0
- package/dist/polling-output-source.js +73 -0
- package/dist/polling-output-source.js.map +1 -0
- package/dist/profile-backend-observation.d.ts +94 -0
- package/dist/profile-backend-observation.d.ts.map +1 -0
- package/dist/profile-backend-observation.js +136 -0
- package/dist/profile-backend-observation.js.map +1 -0
- package/dist/respawn-and-supervise.d.ts +119 -0
- package/dist/respawn-and-supervise.d.ts.map +1 -0
- package/dist/respawn-and-supervise.js +212 -0
- package/dist/respawn-and-supervise.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **The assembly nothing else performed.**
|
|
3
|
+
*
|
|
4
|
+
* Every piece of the runtime existed and none of them were wired together
|
|
5
|
+
* in production code: the controller spawned services, `RuntimeAdapter`
|
|
6
|
+
* could build collectors, `resolveServiceRootForOrigin` could map an origin
|
|
7
|
+
* to a source root, and `EvidenceStore` could persist. Only tests ever
|
|
8
|
+
* connected them, each in its own way, which meant the thing the product
|
|
9
|
+
* actually does had no single implementation to be right or wrong.
|
|
10
|
+
*
|
|
11
|
+
* This module is that implementation. It:
|
|
12
|
+
*
|
|
13
|
+
* 1. runs an `ExecutionController` over a `services` configuration;
|
|
14
|
+
* 2. wraps each spawned process in a **live** `ProcessOutputSource` that
|
|
15
|
+
* polls the accumulated buffer and yields each line exactly once;
|
|
16
|
+
* 3. builds a `CollectorContext` carrying a real `resolveSourceRoot`,
|
|
17
|
+
* closed over the execution's own processes — the channel RT-033 added
|
|
18
|
+
* and RT-029 built the lookup for, which until now nothing populated;
|
|
19
|
+
* 4. starts the adapter's collectors, drains them, stops them;
|
|
20
|
+
* 5. writes every emitted item through `EvidenceStore`, so redaction runs
|
|
21
|
+
* rather than being assumed (plan §28).
|
|
22
|
+
*
|
|
23
|
+
* **What it deliberately does not do.** It does not decide whether a
|
|
24
|
+
* finding exists, does not correlate to graph nodes, and does not drive a
|
|
25
|
+
* browser. Those are separate stages with separate contracts, and folding
|
|
26
|
+
* them in here would make the one place that assembles the runtime also the
|
|
27
|
+
* place that judges it.
|
|
28
|
+
*/
|
|
29
|
+
import { resolveServiceRootForOrigin } from "@descryy/runtime-contracts";
|
|
30
|
+
import { createInboundProxy } from "@descryy/runtime-backend-observation";
|
|
31
|
+
import { ExecutionController, checkDependencyVersions, checkEnvironmentVersion, } from "@descryy/runtime-controller";
|
|
32
|
+
import { EvidenceStore } from "@descryy/runtime-evidence-store";
|
|
33
|
+
import { createPollingProcessOutputSource } from "./polling-output-source.js";
|
|
34
|
+
import { COLLECTOR_VERSION } from "./collector-version.js";
|
|
35
|
+
/**
|
|
36
|
+
* Builds the origin → source-root lookup a collector reads through
|
|
37
|
+
* `CollectorContext.resolveSourceRoot`.
|
|
38
|
+
*
|
|
39
|
+
* This is the piece that had been missing at both ends: RT-029 wrote the
|
|
40
|
+
* lookup and nothing called it; RT-033 added the channel and nothing filled
|
|
41
|
+
* it. It closes over the execution's *own* processes, which is what makes
|
|
42
|
+
* the port→service join possible at all — under ephemeral ports the
|
|
43
|
+
* configuration cannot know the port, so only the running process can say.
|
|
44
|
+
*/
|
|
45
|
+
export function createSourceRootResolver(processes, configuration) {
|
|
46
|
+
return (origin) => resolveServiceRootForOrigin(origin, { processes, configuration });
|
|
47
|
+
}
|
|
48
|
+
export async function runInstrumentedExecution(input) {
|
|
49
|
+
const configuration = input.execution.configuration;
|
|
50
|
+
const controller = ExecutionController.create(input.execution);
|
|
51
|
+
// Closes §34's remaining "runtime self-observability" gap after RT-219:
|
|
52
|
+
// `controller.run()` has exactly one throw path (`controller.ts`'s own
|
|
53
|
+
// `spawnProcess` catch/rethrow, after it has already recorded the
|
|
54
|
+
// failure in `serviceStartResults` and transitioned to `FAILED_START`) --
|
|
55
|
+
// left unguarded here, that throw used to reject this whole function,
|
|
56
|
+
// uncaught, the identical "harness machinery breaks, zero evidence
|
|
57
|
+
// trail" shape RT-219 already fixed one layer up for `collector.start()`.
|
|
58
|
+
// Caught the same way: written through the same `EvidenceStore`, tagged
|
|
59
|
+
// `source: "harness"`. `controller.execution` and
|
|
60
|
+
// `controller.serviceStartResults` are both real at this point (`run()`
|
|
61
|
+
// mutates its private state, including a call to its own `#finish()`,
|
|
62
|
+
// before it ever throws) so the run resolves with what actually happened
|
|
63
|
+
// rather than rejecting the caller's own promise -- the same "resolves
|
|
64
|
+
// normally" contract RT-219 already established.
|
|
65
|
+
let execution;
|
|
66
|
+
try {
|
|
67
|
+
execution = await controller.run(input.runOptions);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
71
|
+
const harnessEvidence = input.store.write({
|
|
72
|
+
executionId: controller.execution.executionId,
|
|
73
|
+
timestamp: new Date().toISOString(),
|
|
74
|
+
source: "harness",
|
|
75
|
+
service: null,
|
|
76
|
+
process: null,
|
|
77
|
+
eventType: "COLLECTOR_ERROR",
|
|
78
|
+
payload: {
|
|
79
|
+
raw: `ExecutionController.run() threw instead of resolving: ${detail}`,
|
|
80
|
+
error: detail,
|
|
81
|
+
},
|
|
82
|
+
traceId: null,
|
|
83
|
+
requestId: null,
|
|
84
|
+
correlationId: null,
|
|
85
|
+
graphNodeId: null,
|
|
86
|
+
sourceLocation: null,
|
|
87
|
+
stackTrace: null,
|
|
88
|
+
confidence: 1,
|
|
89
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
execution: controller.execution,
|
|
93
|
+
evidence: [harnessEvidence],
|
|
94
|
+
collectorCapabilities: [],
|
|
95
|
+
validationError: `ExecutionController.run() threw: ${detail}`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (controller.validationError !== null) {
|
|
99
|
+
return { execution, evidence: [], collectorCapabilities: [], validationError: controller.validationError };
|
|
100
|
+
}
|
|
101
|
+
// One source per spawned service. `serviceName` is what joins a handle
|
|
102
|
+
// back to its configuration entry, and a handle without one cannot be
|
|
103
|
+
// attributed -- skipped rather than guessed at.
|
|
104
|
+
// Declared before the sources close over it: each generator polls until
|
|
105
|
+
// this flips, and the flip is what lets `stop()` finish rather than wait
|
|
106
|
+
// forever on a source still watching a live buffer.
|
|
107
|
+
let finished = false;
|
|
108
|
+
const sources = [];
|
|
109
|
+
for (const handle of execution.processes) {
|
|
110
|
+
if (handle.serviceName === null)
|
|
111
|
+
continue;
|
|
112
|
+
const serviceName = handle.serviceName;
|
|
113
|
+
sources.push(createPollingProcessOutputSource({
|
|
114
|
+
processId: handle.processId,
|
|
115
|
+
readOutput: () => controller.readProcessOutput(serviceName),
|
|
116
|
+
isFinished: () => finished,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
const backendCollectors = input.adapter.createBackendCollectors(sources);
|
|
120
|
+
const emitted = [];
|
|
121
|
+
// `DEC-NEXT-fault-layer-empirical-confirmation.md`'s `dependency`/
|
|
122
|
+
// `environment` mechanisms -- the producer side of the same shape RT-219
|
|
123
|
+
// established for `automation` above: a structural fact the runtime
|
|
124
|
+
// establishes about its own execution environment, tagged
|
|
125
|
+
// `source: "dependency-check"` / `"environment-check"` rather than the
|
|
126
|
+
// service's own domain source, so a reader can tell "the project's
|
|
127
|
+
// declared versions don't match what actually ran" from an observation of
|
|
128
|
+
// the application itself without inspecting payload text. Run once per
|
|
129
|
+
// spawned service (each has its own `cwd`, and therefore potentially its
|
|
130
|
+
// own lockfile/`engines.node`), unconditionally -- "cheap, always
|
|
131
|
+
// available, no rerun needed" per the ruling -- but only ever emitted as
|
|
132
|
+
// evidence when an actual mismatch is found, the same "silence must not
|
|
133
|
+
// manufacture evidence" discipline `"harness"` already observes.
|
|
134
|
+
//
|
|
135
|
+
// The observed Node version is `execution.environmentMetadata`'s own
|
|
136
|
+
// `nodeVersion` -- `process.version` of the controller process, captured
|
|
137
|
+
// once by `captureEnvironmentMetadata` during `controller.run()` above,
|
|
138
|
+
// never re-probed here. It is non-null whenever `validationError` is
|
|
139
|
+
// null (the early return above already excluded the one case where it
|
|
140
|
+
// would not be).
|
|
141
|
+
const observedNodeVersion = execution.environmentMetadata?.nodeVersion ?? process.version;
|
|
142
|
+
for (const handle of execution.processes) {
|
|
143
|
+
if (handle.serviceName === null)
|
|
144
|
+
continue;
|
|
145
|
+
const serviceConfig = configuration.services[handle.serviceName];
|
|
146
|
+
if (serviceConfig === undefined)
|
|
147
|
+
continue;
|
|
148
|
+
const dependencyResult = checkDependencyVersions(serviceConfig.cwd);
|
|
149
|
+
for (const mismatch of dependencyResult.mismatches) {
|
|
150
|
+
emitted.push(input.store.write({
|
|
151
|
+
executionId: execution.executionId,
|
|
152
|
+
timestamp: new Date().toISOString(),
|
|
153
|
+
source: "dependency-check",
|
|
154
|
+
service: handle.serviceName,
|
|
155
|
+
process: handle.processId,
|
|
156
|
+
eventType: "DEPENDENCY_VERSION_MISMATCH",
|
|
157
|
+
payload: {
|
|
158
|
+
raw: `dependency "${mismatch.name}": lockfile declares ${mismatch.declaredVersion}, resolved ${mismatch.resolvedVersion}`,
|
|
159
|
+
name: mismatch.name,
|
|
160
|
+
declaredVersion: mismatch.declaredVersion,
|
|
161
|
+
resolvedVersion: mismatch.resolvedVersion,
|
|
162
|
+
},
|
|
163
|
+
traceId: null,
|
|
164
|
+
requestId: null,
|
|
165
|
+
correlationId: null,
|
|
166
|
+
graphNodeId: null,
|
|
167
|
+
sourceLocation: null,
|
|
168
|
+
stackTrace: null,
|
|
169
|
+
confidence: 1,
|
|
170
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
171
|
+
}));
|
|
172
|
+
}
|
|
173
|
+
const environmentResult = checkEnvironmentVersion(serviceConfig.cwd, observedNodeVersion);
|
|
174
|
+
if (environmentResult.mismatch) {
|
|
175
|
+
emitted.push(input.store.write({
|
|
176
|
+
executionId: execution.executionId,
|
|
177
|
+
timestamp: new Date().toISOString(),
|
|
178
|
+
source: "environment-check",
|
|
179
|
+
service: handle.serviceName,
|
|
180
|
+
process: handle.processId,
|
|
181
|
+
eventType: "ENVIRONMENT_VERSION_MISMATCH",
|
|
182
|
+
payload: {
|
|
183
|
+
raw: `declared node version ${environmentResult.declaredVersion ?? "unknown"} (${environmentResult.declaredSource ?? "unknown"}), observed ${environmentResult.observedVersion}`,
|
|
184
|
+
declaredVersion: environmentResult.declaredVersion,
|
|
185
|
+
declaredSource: environmentResult.declaredSource,
|
|
186
|
+
observedVersion: environmentResult.observedVersion,
|
|
187
|
+
},
|
|
188
|
+
traceId: null,
|
|
189
|
+
requestId: null,
|
|
190
|
+
correlationId: null,
|
|
191
|
+
graphNodeId: null,
|
|
192
|
+
sourceLocation: null,
|
|
193
|
+
stackTrace: null,
|
|
194
|
+
confidence: 1,
|
|
195
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Opt-in InboundProxy wiring (RT-192, DEC-271) -- see `frontWithInboundProxy`'s
|
|
200
|
+
// own doc for what this does and, just as important, what it does not
|
|
201
|
+
// close. Built AFTER `controller.run()` has already returned, so every
|
|
202
|
+
// service's own readiness answer already exists in
|
|
203
|
+
// `controller.serviceStartResults` -- this loop reads that answer, it
|
|
204
|
+
// never re-derives or re-checks it itself.
|
|
205
|
+
const proxies = [];
|
|
206
|
+
if (input.frontWithInboundProxy !== undefined) {
|
|
207
|
+
for (const handle of execution.processes) {
|
|
208
|
+
const serviceName = handle.serviceName;
|
|
209
|
+
if (serviceName === null)
|
|
210
|
+
continue;
|
|
211
|
+
if (input.frontWithInboundProxy[serviceName] !== true)
|
|
212
|
+
continue;
|
|
213
|
+
const readinessOutcome = controller.serviceStartResults.find((result) => result.serviceName === serviceName && result.stage === "readiness");
|
|
214
|
+
if (readinessOutcome?.succeeded !== true || handle.port === null) {
|
|
215
|
+
// Requested but never proven live -- reported as a real
|
|
216
|
+
// COLLECTOR_ERROR, the same shape every other unavailable collector
|
|
217
|
+
// in this function gets, rather than a silent no-proxy fallback
|
|
218
|
+
// ("we did not observe this" vs "there was nothing to observe",
|
|
219
|
+
// plan §17, applies here too).
|
|
220
|
+
emitted.push(input.store.write({
|
|
221
|
+
executionId: execution.executionId,
|
|
222
|
+
timestamp: new Date().toISOString(),
|
|
223
|
+
source: "backend-process",
|
|
224
|
+
service: serviceName,
|
|
225
|
+
process: handle.processId,
|
|
226
|
+
eventType: "COLLECTOR_ERROR",
|
|
227
|
+
payload: {
|
|
228
|
+
raw: `service "${serviceName}" was flagged frontWithInboundProxy but its own readiness never succeeded -- never fronting a process that was not proven live`,
|
|
229
|
+
collectorId: `inbound-proxy:${handle.processId}`,
|
|
230
|
+
},
|
|
231
|
+
traceId: null,
|
|
232
|
+
requestId: null,
|
|
233
|
+
correlationId: null,
|
|
234
|
+
graphNodeId: null,
|
|
235
|
+
sourceLocation: null,
|
|
236
|
+
stackTrace: null,
|
|
237
|
+
confidence: 1,
|
|
238
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
239
|
+
}));
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
proxies.push({
|
|
243
|
+
serviceName,
|
|
244
|
+
proxy: createInboundProxy({
|
|
245
|
+
targetHost: "127.0.0.1",
|
|
246
|
+
targetPort: handle.port,
|
|
247
|
+
processId: handle.processId,
|
|
248
|
+
service: serviceName,
|
|
249
|
+
}),
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const collectors = [...backendCollectors, ...proxies.map((entry) => entry.proxy.collector)];
|
|
254
|
+
const context = {
|
|
255
|
+
executionId: execution.executionId,
|
|
256
|
+
configuration,
|
|
257
|
+
// Redaction runs here, on the way in -- EvidenceStore.write() is the
|
|
258
|
+
// only path that sets redactionStatus, so nothing reaches the returned
|
|
259
|
+
// array without having been through it (plan §28).
|
|
260
|
+
emit: (evidenceInput) => {
|
|
261
|
+
emitted.push(input.store.write({ ...evidenceInput, executionId: execution.executionId }));
|
|
262
|
+
},
|
|
263
|
+
resolveSourceRoot: createSourceRootResolver(execution.processes, configuration),
|
|
264
|
+
};
|
|
265
|
+
// RT-219 (runtime self-observability). `collector.start()`'s documented
|
|
266
|
+
// failure path resolves `{available: false, reason}` -- the loop below
|
|
267
|
+
// already reports that one, tagged with the domain source the collector
|
|
268
|
+
// was going to observe. A collector that instead THROWS out of start()
|
|
269
|
+
// is a different claim: not "I looked and could not," but the harness's
|
|
270
|
+
// own machinery breaking before it ever got that far. Left unguarded,
|
|
271
|
+
// that throw rejects this Promise.all and `runInstrumentedExecution`
|
|
272
|
+
// aborts uncaught -- zero evidence trail for why, the exact "collector
|
|
273
|
+
// failure mistaken for absence of failure" shape plan §17 forbids,
|
|
274
|
+
// applied to the harness's own code instead of the application's.
|
|
275
|
+
// Caught here and written through the same EvidenceStore, tagged
|
|
276
|
+
// `source: "harness"` rather than the collector's domain source, so a
|
|
277
|
+
// reader can tell "our own observer broke" from "the observed system
|
|
278
|
+
// did" without inspecting payload text.
|
|
279
|
+
const startOutcomes = await Promise.all(collectors.map(async (collector) => {
|
|
280
|
+
try {
|
|
281
|
+
return { collector, result: await collector.start(context), threw: false };
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
const detail = error instanceof Error ? `${error.name}: ${error.message}` : String(error);
|
|
285
|
+
emitted.push(input.store.write({
|
|
286
|
+
executionId: execution.executionId,
|
|
287
|
+
timestamp: new Date().toISOString(),
|
|
288
|
+
source: "harness",
|
|
289
|
+
service: null,
|
|
290
|
+
process: null,
|
|
291
|
+
eventType: "COLLECTOR_ERROR",
|
|
292
|
+
payload: {
|
|
293
|
+
raw: `collector "${collector.collectorId}" threw during start() instead of resolving {available:false}: ${detail}`,
|
|
294
|
+
collectorId: collector.collectorId,
|
|
295
|
+
error: detail,
|
|
296
|
+
},
|
|
297
|
+
traceId: null,
|
|
298
|
+
requestId: null,
|
|
299
|
+
correlationId: null,
|
|
300
|
+
graphNodeId: null,
|
|
301
|
+
sourceLocation: null,
|
|
302
|
+
stackTrace: null,
|
|
303
|
+
confidence: 1,
|
|
304
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
305
|
+
}));
|
|
306
|
+
return { collector, result: { available: false, reason: `start() threw: ${detail}` }, threw: true };
|
|
307
|
+
}
|
|
308
|
+
}));
|
|
309
|
+
// A thrown start() was already reported above, under `source: "harness"`
|
|
310
|
+
// -- excluded here so it is not reported a second time under
|
|
311
|
+
// `source: "backend-process"` by the loop below, which would collide
|
|
312
|
+
// the two tags on what is really one failure.
|
|
313
|
+
const unavailable = startOutcomes.filter((entry) => !entry.threw && !entry.result.available);
|
|
314
|
+
// A collector that could not start is reported, never silently absent:
|
|
315
|
+
// "we did not observe this" and "there was nothing to observe" are
|
|
316
|
+
// different claims (plan §17).
|
|
317
|
+
for (const entry of unavailable) {
|
|
318
|
+
emitted.push(input.store.write({
|
|
319
|
+
executionId: execution.executionId,
|
|
320
|
+
timestamp: new Date().toISOString(),
|
|
321
|
+
source: "backend-process",
|
|
322
|
+
service: null,
|
|
323
|
+
process: null,
|
|
324
|
+
eventType: "COLLECTOR_ERROR",
|
|
325
|
+
payload: {
|
|
326
|
+
raw: `collector "${entry.collector.collectorId}" reported unavailable at start: ${entry.result.available ? "" : (entry.result.reason ?? "no reason given")}`,
|
|
327
|
+
collectorId: entry.collector.collectorId,
|
|
328
|
+
},
|
|
329
|
+
traceId: null,
|
|
330
|
+
requestId: null,
|
|
331
|
+
correlationId: null,
|
|
332
|
+
graphNodeId: null,
|
|
333
|
+
sourceLocation: null,
|
|
334
|
+
stackTrace: null,
|
|
335
|
+
confidence: 1,
|
|
336
|
+
collectorVersion: COLLECTOR_VERSION,
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
// Every fronted proxy that actually started (a collector reported
|
|
340
|
+
// `available: false` above never reaches here -- its port stayed null on
|
|
341
|
+
// that codepath, matching `InboundProxy.port()`'s own contract).
|
|
342
|
+
const proxyPorts = {};
|
|
343
|
+
for (const entry of proxies) {
|
|
344
|
+
const port = entry.proxy.port();
|
|
345
|
+
if (port !== null)
|
|
346
|
+
proxyPorts[entry.serviceName] = port;
|
|
347
|
+
}
|
|
348
|
+
await input.onReady?.({ execution, proxyPorts });
|
|
349
|
+
await new Promise((resolve) => setTimeout(resolve, input.observeForMs));
|
|
350
|
+
// Order matters: the sources must be told the process is done before
|
|
351
|
+
// stop() awaits their drain, or stop() waits forever on a generator
|
|
352
|
+
// still polling a live buffer.
|
|
353
|
+
finished = true;
|
|
354
|
+
await Promise.all(collectors.map((collector) => collector.stop()));
|
|
355
|
+
await controller.stop();
|
|
356
|
+
return {
|
|
357
|
+
execution: controller.execution,
|
|
358
|
+
evidence: emitted,
|
|
359
|
+
collectorCapabilities: collectors.map((collector) => ({ collectorId: collector.collectorId, capabilities: collector.capabilities() })),
|
|
360
|
+
validationError: null,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
//# sourceMappingURL=instrumented-execution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrumented-execution.js","sourceRoot":"","sources":["../src/instrumented-execution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles `Agent.java` into `agent.jar` and `Attacher.java` into
|
|
3
|
+
* `Attacher.class`, once, and only when the source is newer than the build
|
|
4
|
+
* output — the same mtime-cache rule `kotlin-server/build.ts` (test fixture
|
|
5
|
+
* side) already uses, applied here to shipped `src/` code instead of a test
|
|
6
|
+
* fixture, because the agent and its launcher are real product code:
|
|
7
|
+
* `attach-to-running-jvm-process.ts` runs the compiled artifacts, it does
|
|
8
|
+
* not compile them itself at call time.
|
|
9
|
+
*
|
|
10
|
+
* **`tools.jar` is JDK-8-only.** `com.sun.tools.attach.VirtualMachine`
|
|
11
|
+
* shipped inside `tools.jar` through JDK 8; from JDK 9 it moved into the
|
|
12
|
+
* `jdk.attach` module and is resolvable on the classpath with no extra jar.
|
|
13
|
+
* `findToolsJarIfPresent` looks for it and returns `null` when absent
|
|
14
|
+
* (JDK 9+, or a JRE with no `tools.jar` at all) — `Attacher.java` is then
|
|
15
|
+
* compiled and later run with no extra classpath entry, which is correct
|
|
16
|
+
* for JDK 9+ but has only been exercised against JDK 8 on this machine (the
|
|
17
|
+
* only JDK installed here); see this module's own decisions-inbox entry for
|
|
18
|
+
* that disclosed gap.
|
|
19
|
+
*
|
|
20
|
+
* **ByteBuddy, vendored the same way `junit-platform-console-standalone` is
|
|
21
|
+
* for the JUnit reporter** (`packages/test-runner/reporters/junit/build.mjs`):
|
|
22
|
+
* one pinned version, fetched once from Maven Central, checksum-verified,
|
|
23
|
+
* cached beside the agent's own sources — never a build tool. `Agent.java`
|
|
24
|
+
* needs a real bytecode-manipulation library for `DispatcherServlet`
|
|
25
|
+
* method-entry advice (RT-201); hand-written raw ASM/bytecode patching for
|
|
26
|
+
* that is not realistic, and Maven/Gradle here would mean resolving a
|
|
27
|
+
* dependency tree for one library this single file uses. The plain
|
|
28
|
+
* `net.bytebuddy:byte-buddy` artifact (not `byte-buddy-dep`) is used
|
|
29
|
+
* specifically because it repackages its own ASM under
|
|
30
|
+
* `net.bytebuddy.jar.asm.*` (verified directly against this exact jar,
|
|
31
|
+
* `unzip -l`) — one self-contained jar, no second dependency to vendor.
|
|
32
|
+
* `Class-Path: byte-buddy-<version>.jar` in `MANIFEST.MF` is a **static,
|
|
33
|
+
* version-pinned line** rather than a generated one, so a version bump is a
|
|
34
|
+
* two-line, reviewable diff (URL/digest here, `Class-Path` in the manifest)
|
|
35
|
+
* exactly like `junit-platform-console-standalone`'s. It sits beside
|
|
36
|
+
* `agent.jar` in the same directory as `Agent.java` itself (below) because
|
|
37
|
+
* the JDK resolves an agent JAR's `Class-Path` manifest entries relative to
|
|
38
|
+
* the agent JAR's own location, for both `-javaagent` and
|
|
39
|
+
* `VirtualMachine.loadAgent` — the same resolution `Attacher.java` relies on
|
|
40
|
+
* already existing for `Agent-Class` itself.
|
|
41
|
+
*
|
|
42
|
+
* **`Agent.java`/`Attacher.java`/`MANIFEST.MF` live in `packages/orchestrator/jvm-agent/`,
|
|
43
|
+
* a sibling of `src/` and `dist/`, NOT inside `src/jvm-agent/` alongside
|
|
44
|
+
* this file.** Found the hard way, while proving RT-201 from a package
|
|
45
|
+
* OTHER than this one (`@descry/vertical-slice`'s test, importing through
|
|
46
|
+
* the compiled `@descryy/runtime-orchestrator` package boundary rather than
|
|
47
|
+
* this repo's own `src/`): `tsc` only ever emits `.js`/`.d.ts` for `.ts`
|
|
48
|
+
* sources, so a `.java` file nested inside `src/jvm-agent/` had no
|
|
49
|
+
* counterpart under `dist/jvm-agent/` at all, and this module's own
|
|
50
|
+
* `import.meta.url`-relative resolution pointed at a directory that only
|
|
51
|
+
* existed when running from source. This is the exact same problem
|
|
52
|
+
* `test-runner-collector.ts` already solved for the JUnit/xUnit reporters
|
|
53
|
+
* (its own comment: *"Computed from `import.meta.url` like the other
|
|
54
|
+
* reporter paths rather than imported from `reporters/junit/build.mjs`:
|
|
55
|
+
* that file is outside this package's `rootDir`"*) — a relative URL that
|
|
56
|
+
* walks OUT of `src/`/`dist/` to a shared sibling resolves identically from
|
|
57
|
+
* either one, since both sit at the same depth under `packages/orchestrator/`.
|
|
58
|
+
* Applied here the same way, one level up from that file's `reporters/`.
|
|
59
|
+
*/
|
|
60
|
+
export declare const JVM_AGENT_DIR: string;
|
|
61
|
+
export declare const BYTEBUDDY_JAR: string;
|
|
62
|
+
/** Fetches the pinned ByteBuddy jar if absent or its checksum no longer matches — refuses a mismatch rather than proceeding, since this jar is both compiled against and loaded into a target JVM. */
|
|
63
|
+
export declare function ensureByteBuddyJar(): Promise<string>;
|
|
64
|
+
/** `$JAVA_HOME/lib/tools.jar` if it exists, else derived from `java`'s own reported `java.home`. `null` when neither yields a real file — the JDK 9+, no-`tools.jar` case. */
|
|
65
|
+
export declare function findToolsJarIfPresent(): string | null;
|
|
66
|
+
/** Compiles `Agent.java` and packages it as `agent.jar` with `Agent-Class` in its manifest. Returns the jar's path. */
|
|
67
|
+
export declare function buildJvmAgentJar(): Promise<string>;
|
|
68
|
+
/** Compiles `Attacher.java` to `Attacher.class` in this same directory. Returns the directory to put on the classpath (the class itself, not a jar — one file, no packaging step needed). */
|
|
69
|
+
export declare function buildAttacherClass(): string;
|
|
70
|
+
/** Ensures a directory exists (for the caller's tmp output file), mirroring the small helper every attach module in this package already needs once for its own scratch state. */
|
|
71
|
+
export declare function ensureDir(path: string): void;
|
|
72
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/jvm-agent/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAQH,eAAO,MAAM,aAAa,QAA6D,CAAC;AAMxF,eAAO,MAAM,aAAa,QAA6D,CAAC;AAMxF,sMAAsM;AACtM,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAe1D;AAMD,8KAA8K;AAC9K,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAYrD;AAED,uHAAuH;AACvH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BxD;AAED,6LAA6L;AAC7L,wBAAgB,kBAAkB,IAAI,MAAM,CAY3C;AAED,kLAAkL;AAClL,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE5C"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles `Agent.java` into `agent.jar` and `Attacher.java` into
|
|
3
|
+
* `Attacher.class`, once, and only when the source is newer than the build
|
|
4
|
+
* output — the same mtime-cache rule `kotlin-server/build.ts` (test fixture
|
|
5
|
+
* side) already uses, applied here to shipped `src/` code instead of a test
|
|
6
|
+
* fixture, because the agent and its launcher are real product code:
|
|
7
|
+
* `attach-to-running-jvm-process.ts` runs the compiled artifacts, it does
|
|
8
|
+
* not compile them itself at call time.
|
|
9
|
+
*
|
|
10
|
+
* **`tools.jar` is JDK-8-only.** `com.sun.tools.attach.VirtualMachine`
|
|
11
|
+
* shipped inside `tools.jar` through JDK 8; from JDK 9 it moved into the
|
|
12
|
+
* `jdk.attach` module and is resolvable on the classpath with no extra jar.
|
|
13
|
+
* `findToolsJarIfPresent` looks for it and returns `null` when absent
|
|
14
|
+
* (JDK 9+, or a JRE with no `tools.jar` at all) — `Attacher.java` is then
|
|
15
|
+
* compiled and later run with no extra classpath entry, which is correct
|
|
16
|
+
* for JDK 9+ but has only been exercised against JDK 8 on this machine (the
|
|
17
|
+
* only JDK installed here); see this module's own decisions-inbox entry for
|
|
18
|
+
* that disclosed gap.
|
|
19
|
+
*
|
|
20
|
+
* **ByteBuddy, vendored the same way `junit-platform-console-standalone` is
|
|
21
|
+
* for the JUnit reporter** (`packages/test-runner/reporters/junit/build.mjs`):
|
|
22
|
+
* one pinned version, fetched once from Maven Central, checksum-verified,
|
|
23
|
+
* cached beside the agent's own sources — never a build tool. `Agent.java`
|
|
24
|
+
* needs a real bytecode-manipulation library for `DispatcherServlet`
|
|
25
|
+
* method-entry advice (RT-201); hand-written raw ASM/bytecode patching for
|
|
26
|
+
* that is not realistic, and Maven/Gradle here would mean resolving a
|
|
27
|
+
* dependency tree for one library this single file uses. The plain
|
|
28
|
+
* `net.bytebuddy:byte-buddy` artifact (not `byte-buddy-dep`) is used
|
|
29
|
+
* specifically because it repackages its own ASM under
|
|
30
|
+
* `net.bytebuddy.jar.asm.*` (verified directly against this exact jar,
|
|
31
|
+
* `unzip -l`) — one self-contained jar, no second dependency to vendor.
|
|
32
|
+
* `Class-Path: byte-buddy-<version>.jar` in `MANIFEST.MF` is a **static,
|
|
33
|
+
* version-pinned line** rather than a generated one, so a version bump is a
|
|
34
|
+
* two-line, reviewable diff (URL/digest here, `Class-Path` in the manifest)
|
|
35
|
+
* exactly like `junit-platform-console-standalone`'s. It sits beside
|
|
36
|
+
* `agent.jar` in the same directory as `Agent.java` itself (below) because
|
|
37
|
+
* the JDK resolves an agent JAR's `Class-Path` manifest entries relative to
|
|
38
|
+
* the agent JAR's own location, for both `-javaagent` and
|
|
39
|
+
* `VirtualMachine.loadAgent` — the same resolution `Attacher.java` relies on
|
|
40
|
+
* already existing for `Agent-Class` itself.
|
|
41
|
+
*
|
|
42
|
+
* **`Agent.java`/`Attacher.java`/`MANIFEST.MF` live in `packages/orchestrator/jvm-agent/`,
|
|
43
|
+
* a sibling of `src/` and `dist/`, NOT inside `src/jvm-agent/` alongside
|
|
44
|
+
* this file.** Found the hard way, while proving RT-201 from a package
|
|
45
|
+
* OTHER than this one (`@descry/vertical-slice`'s test, importing through
|
|
46
|
+
* the compiled `@descryy/runtime-orchestrator` package boundary rather than
|
|
47
|
+
* this repo's own `src/`): `tsc` only ever emits `.js`/`.d.ts` for `.ts`
|
|
48
|
+
* sources, so a `.java` file nested inside `src/jvm-agent/` had no
|
|
49
|
+
* counterpart under `dist/jvm-agent/` at all, and this module's own
|
|
50
|
+
* `import.meta.url`-relative resolution pointed at a directory that only
|
|
51
|
+
* existed when running from source. This is the exact same problem
|
|
52
|
+
* `test-runner-collector.ts` already solved for the JUnit/xUnit reporters
|
|
53
|
+
* (its own comment: *"Computed from `import.meta.url` like the other
|
|
54
|
+
* reporter paths rather than imported from `reporters/junit/build.mjs`:
|
|
55
|
+
* that file is outside this package's `rootDir`"*) — a relative URL that
|
|
56
|
+
* walks OUT of `src/`/`dist/` to a shared sibling resolves identically from
|
|
57
|
+
* either one, since both sit at the same depth under `packages/orchestrator/`.
|
|
58
|
+
* Applied here the same way, one level up from that file's `reporters/`.
|
|
59
|
+
*/
|
|
60
|
+
import { spawnSync } from "node:child_process";
|
|
61
|
+
import { createHash } from "node:crypto";
|
|
62
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
63
|
+
import { join } from "node:path";
|
|
64
|
+
import { fileURLToPath } from "node:url";
|
|
65
|
+
export const JVM_AGENT_DIR = fileURLToPath(new URL("../../jvm-agent", import.meta.url));
|
|
66
|
+
/** Pinned. A version bump changes the URL, the digest, and `MANIFEST.MF`'s `Class-Path` line, in one reviewable diff. */
|
|
67
|
+
const BYTEBUDDY_VERSION = "1.15.11";
|
|
68
|
+
const BYTEBUDDY_SHA256 = "fa08998aae1e7bdae83bde0712c50e8444d71c0e0c196bb2247ade8d4ad0eb90";
|
|
69
|
+
const BYTEBUDDY_URL = `https://repo1.maven.org/maven2/net/bytebuddy/byte-buddy/${BYTEBUDDY_VERSION}/byte-buddy-${BYTEBUDDY_VERSION}.jar`;
|
|
70
|
+
export const BYTEBUDDY_JAR = join(JVM_AGENT_DIR, `byte-buddy-${BYTEBUDDY_VERSION}.jar`);
|
|
71
|
+
function digestOf(path) {
|
|
72
|
+
return createHash("sha256").update(readFileSync(path)).digest("hex");
|
|
73
|
+
}
|
|
74
|
+
/** Fetches the pinned ByteBuddy jar if absent or its checksum no longer matches — refuses a mismatch rather than proceeding, since this jar is both compiled against and loaded into a target JVM. */
|
|
75
|
+
export async function ensureByteBuddyJar() {
|
|
76
|
+
if (existsSync(BYTEBUDDY_JAR) && digestOf(BYTEBUDDY_JAR) === BYTEBUDDY_SHA256)
|
|
77
|
+
return BYTEBUDDY_JAR;
|
|
78
|
+
mkdirSync(JVM_AGENT_DIR, { recursive: true });
|
|
79
|
+
const response = await fetch(BYTEBUDDY_URL);
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
throw new Error(`jvm-agent build: could not fetch ${BYTEBUDDY_URL} — HTTP ${String(response.status)}`);
|
|
82
|
+
}
|
|
83
|
+
writeFileSync(BYTEBUDDY_JAR, Buffer.from(await response.arrayBuffer()));
|
|
84
|
+
const actual = digestOf(BYTEBUDDY_JAR);
|
|
85
|
+
if (actual !== BYTEBUDDY_SHA256) {
|
|
86
|
+
throw new Error(`jvm-agent build: checksum mismatch for ${BYTEBUDDY_JAR}\n expected ${BYTEBUDDY_SHA256}\n actual ${actual}`);
|
|
87
|
+
}
|
|
88
|
+
return BYTEBUDDY_JAR;
|
|
89
|
+
}
|
|
90
|
+
function newerThan(output, source) {
|
|
91
|
+
return existsSync(output) && statSync(output).mtimeMs >= statSync(source).mtimeMs;
|
|
92
|
+
}
|
|
93
|
+
/** `$JAVA_HOME/lib/tools.jar` if it exists, else derived from `java`'s own reported `java.home`. `null` when neither yields a real file — the JDK 9+, no-`tools.jar` case. */
|
|
94
|
+
export function findToolsJarIfPresent() {
|
|
95
|
+
const fromEnv = process.env["JAVA_HOME"];
|
|
96
|
+
if (fromEnv !== undefined) {
|
|
97
|
+
const candidate = join(fromEnv, "lib", "tools.jar");
|
|
98
|
+
if (existsSync(candidate))
|
|
99
|
+
return candidate;
|
|
100
|
+
}
|
|
101
|
+
const probe = spawnSync("java", ["-XshowSettings:properties", "-version"], { encoding: "utf8" });
|
|
102
|
+
const combined = `${probe.stdout ?? ""}${probe.stderr ?? ""}`;
|
|
103
|
+
const match = /java\.home\s*=\s*(.+)/.exec(combined);
|
|
104
|
+
if (match?.[1] === undefined)
|
|
105
|
+
return null;
|
|
106
|
+
const candidate = join(match[1].trim(), "lib", "tools.jar");
|
|
107
|
+
return existsSync(candidate) ? candidate : null;
|
|
108
|
+
}
|
|
109
|
+
/** Compiles `Agent.java` and packages it as `agent.jar` with `Agent-Class` in its manifest. Returns the jar's path. */
|
|
110
|
+
export async function buildJvmAgentJar() {
|
|
111
|
+
const source = join(JVM_AGENT_DIR, "Agent.java");
|
|
112
|
+
const jarPath = join(JVM_AGENT_DIR, "agent.jar");
|
|
113
|
+
const byteBuddyJar = await ensureByteBuddyJar();
|
|
114
|
+
// Cache invalidates on either input changing -- a ByteBuddy version bump
|
|
115
|
+
// (new jar path/mtime) must also trigger a rebuild, not just an Agent.java
|
|
116
|
+
// edit, since the compiled advice classes are compiled against it.
|
|
117
|
+
if (newerThan(jarPath, source) && newerThan(jarPath, byteBuddyJar))
|
|
118
|
+
return jarPath;
|
|
119
|
+
const compiled = spawnSync("javac", ["-cp", byteBuddyJar, "-d", JVM_AGENT_DIR, source], { encoding: "utf8", timeout: 60_000 });
|
|
120
|
+
if (compiled.status !== 0) {
|
|
121
|
+
throw new Error(`javac failed to compile Agent.java. This is a toolchain failure, not a test failure:\n${compiled.stdout ?? ""}${compiled.stderr ?? ""}`);
|
|
122
|
+
}
|
|
123
|
+
// `Agent.java` now declares nested static classes (the ByteBuddy advice)
|
|
124
|
+
// -- `javac` emits one `Agent$Name.class` per nested class alongside
|
|
125
|
+
// `Agent.class`, and every one of them must be in the jar or the JVM
|
|
126
|
+
// throws NoClassDefFoundError the first time DispatcherServlet is loaded
|
|
127
|
+
// in the target and the advice class is needed.
|
|
128
|
+
const agentClassFiles = readdirSync(JVM_AGENT_DIR).filter((name) => name === "Agent.class" || name.startsWith("Agent$"));
|
|
129
|
+
const jarArgs = ["cfm", jarPath, join(JVM_AGENT_DIR, "MANIFEST.MF")];
|
|
130
|
+
for (const classFile of agentClassFiles)
|
|
131
|
+
jarArgs.push("-C", JVM_AGENT_DIR, classFile);
|
|
132
|
+
const jarred = spawnSync("jar", jarArgs, { encoding: "utf8", timeout: 30_000 });
|
|
133
|
+
if (jarred.status !== 0) {
|
|
134
|
+
throw new Error(`jar failed to package agent.jar:\n${jarred.stdout ?? ""}${jarred.stderr ?? ""}`);
|
|
135
|
+
}
|
|
136
|
+
return jarPath;
|
|
137
|
+
}
|
|
138
|
+
/** Compiles `Attacher.java` to `Attacher.class` in this same directory. Returns the directory to put on the classpath (the class itself, not a jar — one file, no packaging step needed). */
|
|
139
|
+
export function buildAttacherClass() {
|
|
140
|
+
const source = join(JVM_AGENT_DIR, "Attacher.java");
|
|
141
|
+
const classFile = join(JVM_AGENT_DIR, "Attacher.class");
|
|
142
|
+
if (newerThan(classFile, source))
|
|
143
|
+
return JVM_AGENT_DIR;
|
|
144
|
+
const toolsJar = findToolsJarIfPresent();
|
|
145
|
+
const args = toolsJar !== null ? ["-cp", toolsJar, "-d", JVM_AGENT_DIR, source] : ["-d", JVM_AGENT_DIR, source];
|
|
146
|
+
const compiled = spawnSync("javac", args, { encoding: "utf8", timeout: 60_000 });
|
|
147
|
+
if (compiled.status !== 0) {
|
|
148
|
+
throw new Error(`javac failed to compile Attacher.java. This is a toolchain failure, not a test failure:\n${compiled.stdout ?? ""}${compiled.stderr ?? ""}`);
|
|
149
|
+
}
|
|
150
|
+
return JVM_AGENT_DIR;
|
|
151
|
+
}
|
|
152
|
+
/** Ensures a directory exists (for the caller's tmp output file), mirroring the small helper every attach module in this package already needs once for its own scratch state. */
|
|
153
|
+
export function ensureDir(path) {
|
|
154
|
+
mkdirSync(path, { recursive: true });
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/jvm-agent/build.ts"],"names":[],"mappings":"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"}
|