terminalhire 0.42.21 → 0.42.23
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/bin/jpi-claim.js +696 -181
- package/dist/bin/jpi-dispatch.js +819 -296
- package/dist/bin/jpi-mcp.js +703 -188
- package/dist/bin/jpi-run.js +600 -77
- package/dist/bin/proxy/egressProxy.js +25 -0
- package/package.json +1 -1
package/dist/bin/jpi-mcp.js
CHANGED
|
@@ -2570,11 +2570,11 @@ function parseGitHubRef(url) {
|
|
|
2570
2570
|
kind: m[3] === "pull" ? "pull" : "issue"
|
|
2571
2571
|
};
|
|
2572
2572
|
}
|
|
2573
|
-
async function ghGraphQL(
|
|
2573
|
+
async function ghGraphQL(query2, variables, token, signal, governor) {
|
|
2574
2574
|
const init = {
|
|
2575
2575
|
method: "POST",
|
|
2576
2576
|
headers: { ...ghHeaders(token), "Content-Type": "application/json" },
|
|
2577
|
-
body: JSON.stringify({ query, variables }),
|
|
2577
|
+
body: JSON.stringify({ query: query2, variables }),
|
|
2578
2578
|
signal
|
|
2579
2579
|
};
|
|
2580
2580
|
if (governor) {
|
|
@@ -12926,8 +12926,8 @@ var init_stringify = __esm({
|
|
|
12926
12926
|
});
|
|
12927
12927
|
|
|
12928
12928
|
// ../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs
|
|
12929
|
-
function stringifyQuery(
|
|
12930
|
-
return stringify(
|
|
12929
|
+
function stringifyQuery(query2) {
|
|
12930
|
+
return stringify(query2, { arrayFormat: "brackets" });
|
|
12931
12931
|
}
|
|
12932
12932
|
var init_query = __esm({
|
|
12933
12933
|
"../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs"() {
|
|
@@ -15011,9 +15011,9 @@ var init_deployment_runs = __esm({
|
|
|
15011
15011
|
* ```
|
|
15012
15012
|
*/
|
|
15013
15013
|
list(params = {}, options) {
|
|
15014
|
-
const { betas, ...
|
|
15014
|
+
const { betas, ...query2 } = params ?? {};
|
|
15015
15015
|
return this._client.getAPIList("/v1/deployment_runs?beta=true", PageCursor, {
|
|
15016
|
-
query,
|
|
15016
|
+
query: query2,
|
|
15017
15017
|
...options,
|
|
15018
15018
|
headers: buildHeaders([
|
|
15019
15019
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -15125,9 +15125,9 @@ var init_deployments = __esm({
|
|
|
15125
15125
|
* ```
|
|
15126
15126
|
*/
|
|
15127
15127
|
list(params = {}, options) {
|
|
15128
|
-
const { betas, ...
|
|
15128
|
+
const { betas, ...query2 } = params ?? {};
|
|
15129
15129
|
return this._client.getAPIList("/v1/deployments?beta=true", PageCursor, {
|
|
15130
|
-
query,
|
|
15130
|
+
query: query2,
|
|
15131
15131
|
...options,
|
|
15132
15132
|
headers: buildHeaders([
|
|
15133
15133
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -15287,9 +15287,9 @@ var init_dreams = __esm({
|
|
|
15287
15287
|
* ```
|
|
15288
15288
|
*/
|
|
15289
15289
|
list(params = {}, options) {
|
|
15290
|
-
const { betas, ...
|
|
15290
|
+
const { betas, ...query2 } = params ?? {};
|
|
15291
15291
|
return this._client.getAPIList("/v1/dreams?beta=true", PageCursor, {
|
|
15292
|
-
query,
|
|
15292
|
+
query: query2,
|
|
15293
15293
|
...options,
|
|
15294
15294
|
headers: buildHeaders([
|
|
15295
15295
|
{ "anthropic-beta": [...betas ?? [], "dreaming-2026-04-21"].toString() },
|
|
@@ -15420,9 +15420,9 @@ var init_files = __esm({
|
|
|
15420
15420
|
* ```
|
|
15421
15421
|
*/
|
|
15422
15422
|
list(params = {}, options) {
|
|
15423
|
-
const { betas, ...
|
|
15423
|
+
const { betas, ...query2 } = params ?? {};
|
|
15424
15424
|
return this._client.getAPIList("/v1/files?beta=true", Page, {
|
|
15425
|
-
query,
|
|
15425
|
+
query: query2,
|
|
15426
15426
|
...options,
|
|
15427
15427
|
headers: buildHeaders([
|
|
15428
15428
|
{ "anthropic-beta": [...betas ?? [], "files-api-2025-04-14"].toString() },
|
|
@@ -15570,9 +15570,9 @@ var init_models = __esm({
|
|
|
15570
15570
|
* ```
|
|
15571
15571
|
*/
|
|
15572
15572
|
list(params = {}, options) {
|
|
15573
|
-
const { betas, ...
|
|
15573
|
+
const { betas, ...query2 } = params ?? {};
|
|
15574
15574
|
return this._client.getAPIList("/v1/models?beta=true", Page, {
|
|
15575
|
-
query,
|
|
15575
|
+
query: query2,
|
|
15576
15576
|
...options,
|
|
15577
15577
|
headers: buildHeaders([
|
|
15578
15578
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -15669,9 +15669,9 @@ var init_user_profiles = __esm({
|
|
|
15669
15669
|
* ```
|
|
15670
15670
|
*/
|
|
15671
15671
|
list(params = {}, options) {
|
|
15672
|
-
const { betas, ...
|
|
15672
|
+
const { betas, ...query2 } = params ?? {};
|
|
15673
15673
|
return this._client.getAPIList("/v1/user_profiles?beta=true", PageCursor, {
|
|
15674
|
-
query,
|
|
15674
|
+
query: query2,
|
|
15675
15675
|
...options,
|
|
15676
15676
|
headers: buildHeaders([
|
|
15677
15677
|
{ "anthropic-beta": [...betas ?? [], "user-profiles-2026-03-24"].toString() },
|
|
@@ -16530,9 +16530,9 @@ var init_versions = __esm({
|
|
|
16530
16530
|
* ```
|
|
16531
16531
|
*/
|
|
16532
16532
|
list(agentID, params = {}, options) {
|
|
16533
|
-
const { betas, ...
|
|
16533
|
+
const { betas, ...query2 } = params ?? {};
|
|
16534
16534
|
return this._client.getAPIList(path`/v1/agents/${agentID}/versions?beta=true`, PageCursor, {
|
|
16535
|
-
query,
|
|
16535
|
+
query: query2,
|
|
16536
16536
|
...options,
|
|
16537
16537
|
headers: buildHeaders([
|
|
16538
16538
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -16595,9 +16595,9 @@ var init_agents = __esm({
|
|
|
16595
16595
|
* ```
|
|
16596
16596
|
*/
|
|
16597
16597
|
retrieve(agentID, params = {}, options) {
|
|
16598
|
-
const { betas, ...
|
|
16598
|
+
const { betas, ...query2 } = params ?? {};
|
|
16599
16599
|
return this._client.get(path`/v1/agents/${agentID}?beta=true`, {
|
|
16600
|
-
query,
|
|
16600
|
+
query: query2,
|
|
16601
16601
|
...options,
|
|
16602
16602
|
headers: buildHeaders([
|
|
16603
16603
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -16640,9 +16640,9 @@ var init_agents = __esm({
|
|
|
16640
16640
|
* ```
|
|
16641
16641
|
*/
|
|
16642
16642
|
list(params = {}, options) {
|
|
16643
|
-
const { betas, ...
|
|
16643
|
+
const { betas, ...query2 } = params ?? {};
|
|
16644
16644
|
return this._client.getAPIList("/v1/agents?beta=true", PageCursor, {
|
|
16645
|
-
query,
|
|
16645
|
+
query: query2,
|
|
16646
16646
|
...options,
|
|
16647
16647
|
headers: buildHeaders([
|
|
16648
16648
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -18732,9 +18732,9 @@ var init_work = __esm({
|
|
|
18732
18732
|
* ```
|
|
18733
18733
|
*/
|
|
18734
18734
|
list(environmentID, params = {}, options) {
|
|
18735
|
-
const { betas, ...
|
|
18735
|
+
const { betas, ...query2 } = params ?? {};
|
|
18736
18736
|
return this._client.getAPIList(path`/v1/environments/${environmentID}/work?beta=true`, PageCursor, {
|
|
18737
|
-
query,
|
|
18737
|
+
query: query2,
|
|
18738
18738
|
...options,
|
|
18739
18739
|
headers: buildHeaders([
|
|
18740
18740
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -18813,9 +18813,9 @@ var init_work = __esm({
|
|
|
18813
18813
|
* ```
|
|
18814
18814
|
*/
|
|
18815
18815
|
poll(environmentID, params = {}, options) {
|
|
18816
|
-
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...
|
|
18816
|
+
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...query2 } = params ?? {};
|
|
18817
18817
|
return this._client.get(path`/v1/environments/${environmentID}/work/poll?beta=true`, {
|
|
18818
|
-
query,
|
|
18818
|
+
query: query2,
|
|
18819
18819
|
...options,
|
|
18820
18820
|
headers: buildHeaders([
|
|
18821
18821
|
{
|
|
@@ -19012,9 +19012,9 @@ var init_environments = __esm({
|
|
|
19012
19012
|
* ```
|
|
19013
19013
|
*/
|
|
19014
19014
|
list(params = {}, options) {
|
|
19015
|
-
const { betas, ...
|
|
19015
|
+
const { betas, ...query2 } = params ?? {};
|
|
19016
19016
|
return this._client.getAPIList("/v1/environments?beta=true", PageCursor, {
|
|
19017
|
-
query,
|
|
19017
|
+
query: query2,
|
|
19018
19018
|
...options,
|
|
19019
19019
|
headers: buildHeaders([
|
|
19020
19020
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -19117,9 +19117,9 @@ var init_memories = __esm({
|
|
|
19117
19117
|
* ```
|
|
19118
19118
|
*/
|
|
19119
19119
|
retrieve(memoryID, params, options) {
|
|
19120
|
-
const { memory_store_id, betas, ...
|
|
19120
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
19121
19121
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memories/${memoryID}?beta=true`, {
|
|
19122
|
-
query,
|
|
19122
|
+
query: query2,
|
|
19123
19123
|
...options,
|
|
19124
19124
|
headers: buildHeaders([
|
|
19125
19125
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19165,9 +19165,9 @@ var init_memories = __esm({
|
|
|
19165
19165
|
* ```
|
|
19166
19166
|
*/
|
|
19167
19167
|
list(memoryStoreID, params = {}, options) {
|
|
19168
|
-
const { betas, ...
|
|
19168
|
+
const { betas, ...query2 } = params ?? {};
|
|
19169
19169
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memories?beta=true`, PageCursor, {
|
|
19170
|
-
query,
|
|
19170
|
+
query: query2,
|
|
19171
19171
|
...options,
|
|
19172
19172
|
headers: buildHeaders([
|
|
19173
19173
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19225,9 +19225,9 @@ var init_memory_versions = __esm({
|
|
|
19225
19225
|
* ```
|
|
19226
19226
|
*/
|
|
19227
19227
|
retrieve(memoryVersionID, params, options) {
|
|
19228
|
-
const { memory_store_id, betas, ...
|
|
19228
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
19229
19229
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memory_versions/${memoryVersionID}?beta=true`, {
|
|
19230
|
-
query,
|
|
19230
|
+
query: query2,
|
|
19231
19231
|
...options,
|
|
19232
19232
|
headers: buildHeaders([
|
|
19233
19233
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19249,9 +19249,9 @@ var init_memory_versions = __esm({
|
|
|
19249
19249
|
* ```
|
|
19250
19250
|
*/
|
|
19251
19251
|
list(memoryStoreID, params = {}, options) {
|
|
19252
|
-
const { betas, ...
|
|
19252
|
+
const { betas, ...query2 } = params ?? {};
|
|
19253
19253
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memory_versions?beta=true`, PageCursor, {
|
|
19254
|
-
query,
|
|
19254
|
+
query: query2,
|
|
19255
19255
|
...options,
|
|
19256
19256
|
headers: buildHeaders([
|
|
19257
19257
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19377,9 +19377,9 @@ var init_memory_stores = __esm({
|
|
|
19377
19377
|
* ```
|
|
19378
19378
|
*/
|
|
19379
19379
|
list(params = {}, options) {
|
|
19380
|
-
const { betas, ...
|
|
19380
|
+
const { betas, ...query2 } = params ?? {};
|
|
19381
19381
|
return this._client.getAPIList("/v1/memory_stores?beta=true", PageCursor, {
|
|
19382
|
-
query,
|
|
19382
|
+
query: query2,
|
|
19383
19383
|
...options,
|
|
19384
19384
|
headers: buildHeaders([
|
|
19385
19385
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19577,9 +19577,9 @@ var init_batches = __esm({
|
|
|
19577
19577
|
* ```
|
|
19578
19578
|
*/
|
|
19579
19579
|
list(params = {}, options) {
|
|
19580
|
-
const { betas, ...
|
|
19580
|
+
const { betas, ...query2 } = params ?? {};
|
|
19581
19581
|
return this._client.getAPIList("/v1/messages/batches?beta=true", Page, {
|
|
19582
|
-
query,
|
|
19582
|
+
query: query2,
|
|
19583
19583
|
...options,
|
|
19584
19584
|
headers: buildHeaders([
|
|
19585
19585
|
{ "anthropic-beta": [...betas ?? [], "message-batches-2024-09-24"].toString() },
|
|
@@ -21252,9 +21252,9 @@ var init_events = __esm({
|
|
|
21252
21252
|
* ```
|
|
21253
21253
|
*/
|
|
21254
21254
|
list(sessionID, params = {}, options) {
|
|
21255
|
-
const { betas, ...
|
|
21255
|
+
const { betas, ...query2 } = params ?? {};
|
|
21256
21256
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/events?beta=true`, PageCursor, {
|
|
21257
|
-
query,
|
|
21257
|
+
query: query2,
|
|
21258
21258
|
...options,
|
|
21259
21259
|
headers: buildHeaders([
|
|
21260
21260
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21309,9 +21309,9 @@ var init_events = __esm({
|
|
|
21309
21309
|
* ```
|
|
21310
21310
|
*/
|
|
21311
21311
|
stream(sessionID, params = {}, options) {
|
|
21312
|
-
const { betas, ...
|
|
21312
|
+
const { betas, ...query2 } = params ?? {};
|
|
21313
21313
|
return this._client.get(path`/v1/sessions/${sessionID}/events/stream?beta=true`, {
|
|
21314
|
-
query,
|
|
21314
|
+
query: query2,
|
|
21315
21315
|
...options,
|
|
21316
21316
|
headers: buildHeaders([
|
|
21317
21317
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21419,9 +21419,9 @@ var init_resources = __esm({
|
|
|
21419
21419
|
* ```
|
|
21420
21420
|
*/
|
|
21421
21421
|
list(sessionID, params = {}, options) {
|
|
21422
|
-
const { betas, ...
|
|
21422
|
+
const { betas, ...query2 } = params ?? {};
|
|
21423
21423
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/resources?beta=true`, PageCursor, {
|
|
21424
|
-
query,
|
|
21424
|
+
query: query2,
|
|
21425
21425
|
...options,
|
|
21426
21426
|
headers: buildHeaders([
|
|
21427
21427
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21506,9 +21506,9 @@ var init_events2 = __esm({
|
|
|
21506
21506
|
* ```
|
|
21507
21507
|
*/
|
|
21508
21508
|
list(threadID, params, options) {
|
|
21509
|
-
const { session_id, betas, ...
|
|
21509
|
+
const { session_id, betas, ...query2 } = params;
|
|
21510
21510
|
return this._client.getAPIList(path`/v1/sessions/${session_id}/threads/${threadID}/events?beta=true`, PageCursor, {
|
|
21511
|
-
query,
|
|
21511
|
+
query: query2,
|
|
21512
21512
|
...options,
|
|
21513
21513
|
headers: buildHeaders([
|
|
21514
21514
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21595,9 +21595,9 @@ var init_threads = __esm({
|
|
|
21595
21595
|
* ```
|
|
21596
21596
|
*/
|
|
21597
21597
|
list(sessionID, params = {}, options) {
|
|
21598
|
-
const { betas, ...
|
|
21598
|
+
const { betas, ...query2 } = params ?? {};
|
|
21599
21599
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/threads?beta=true`, PageCursor, {
|
|
21600
|
-
query,
|
|
21600
|
+
query: query2,
|
|
21601
21601
|
...options,
|
|
21602
21602
|
headers: buildHeaders([
|
|
21603
21603
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21732,9 +21732,9 @@ var init_sessions = __esm({
|
|
|
21732
21732
|
* ```
|
|
21733
21733
|
*/
|
|
21734
21734
|
list(params = {}, options) {
|
|
21735
|
-
const { betas, ...
|
|
21735
|
+
const { betas, ...query2 } = params ?? {};
|
|
21736
21736
|
return this._client.getAPIList("/v1/sessions?beta=true", BidirectionalPageCursor, {
|
|
21737
|
-
query,
|
|
21737
|
+
query: query2,
|
|
21738
21738
|
...options,
|
|
21739
21739
|
headers: buildHeaders([
|
|
21740
21740
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21859,9 +21859,9 @@ var init_versions2 = __esm({
|
|
|
21859
21859
|
* ```
|
|
21860
21860
|
*/
|
|
21861
21861
|
list(skillID, params = {}, options) {
|
|
21862
|
-
const { betas, ...
|
|
21862
|
+
const { betas, ...query2 } = params ?? {};
|
|
21863
21863
|
return this._client.getAPIList(path`/v1/skills/${skillID}/versions?beta=true`, PageCursor, {
|
|
21864
|
-
query,
|
|
21864
|
+
query: query2,
|
|
21865
21865
|
...options,
|
|
21866
21866
|
headers: buildHeaders([
|
|
21867
21867
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -21990,9 +21990,9 @@ var init_skills2 = __esm({
|
|
|
21990
21990
|
* ```
|
|
21991
21991
|
*/
|
|
21992
21992
|
list(params = {}, options) {
|
|
21993
|
-
const { betas, ...
|
|
21993
|
+
const { betas, ...query2 } = params ?? {};
|
|
21994
21994
|
return this._client.getAPIList("/v1/skills?beta=true", PageCursor, {
|
|
21995
|
-
query,
|
|
21995
|
+
query: query2,
|
|
21996
21996
|
...options,
|
|
21997
21997
|
headers: buildHeaders([
|
|
21998
21998
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -22110,9 +22110,9 @@ var init_certificates = __esm({
|
|
|
22110
22110
|
* ```
|
|
22111
22111
|
*/
|
|
22112
22112
|
list(tunnelID, params = {}, options) {
|
|
22113
|
-
const { betas, ...
|
|
22113
|
+
const { betas, ...query2 } = params ?? {};
|
|
22114
22114
|
return this._client.getAPIList(path`/v1/tunnels/${tunnelID}/certificates?beta=true`, PageCursor, {
|
|
22115
|
-
query,
|
|
22115
|
+
query: query2,
|
|
22116
22116
|
...options,
|
|
22117
22117
|
headers: buildHeaders([
|
|
22118
22118
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -22239,9 +22239,9 @@ var init_tunnels = __esm({
|
|
|
22239
22239
|
* ```
|
|
22240
22240
|
*/
|
|
22241
22241
|
list(params = {}, options) {
|
|
22242
|
-
const { betas, ...
|
|
22242
|
+
const { betas, ...query2 } = params ?? {};
|
|
22243
22243
|
return this._client.getAPIList("/v1/tunnels?beta=true", PageCursor, {
|
|
22244
|
-
query,
|
|
22244
|
+
query: query2,
|
|
22245
22245
|
...options,
|
|
22246
22246
|
headers: buildHeaders([
|
|
22247
22247
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -22435,9 +22435,9 @@ var init_credentials2 = __esm({
|
|
|
22435
22435
|
* ```
|
|
22436
22436
|
*/
|
|
22437
22437
|
list(vaultID, params = {}, options) {
|
|
22438
|
-
const { betas, ...
|
|
22438
|
+
const { betas, ...query2 } = params ?? {};
|
|
22439
22439
|
return this._client.getAPIList(path`/v1/vaults/${vaultID}/credentials?beta=true`, PageCursor, {
|
|
22440
|
-
query,
|
|
22440
|
+
query: query2,
|
|
22441
22441
|
...options,
|
|
22442
22442
|
headers: buildHeaders([
|
|
22443
22443
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -22608,9 +22608,9 @@ var init_vaults = __esm({
|
|
|
22608
22608
|
* ```
|
|
22609
22609
|
*/
|
|
22610
22610
|
list(params = {}, options) {
|
|
22611
|
-
const { betas, ...
|
|
22611
|
+
const { betas, ...query2 } = params ?? {};
|
|
22612
22612
|
return this._client.getAPIList("/v1/vaults?beta=true", PageCursor, {
|
|
22613
|
-
query,
|
|
22613
|
+
query: query2,
|
|
22614
22614
|
...options,
|
|
22615
22615
|
headers: buildHeaders([
|
|
22616
22616
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -23496,8 +23496,8 @@ var init_batches2 = __esm({
|
|
|
23496
23496
|
* }
|
|
23497
23497
|
* ```
|
|
23498
23498
|
*/
|
|
23499
|
-
list(
|
|
23500
|
-
return this._client.getAPIList("/v1/messages/batches", Page, { query, ...options });
|
|
23499
|
+
list(query2 = {}, options) {
|
|
23500
|
+
return this._client.getAPIList("/v1/messages/batches", Page, { query: query2, ...options });
|
|
23501
23501
|
}
|
|
23502
23502
|
/**
|
|
23503
23503
|
* Delete a Message Batch.
|
|
@@ -23753,9 +23753,9 @@ var init_models2 = __esm({
|
|
|
23753
23753
|
* use in the API. More recently released models are listed first.
|
|
23754
23754
|
*/
|
|
23755
23755
|
list(params = {}, options) {
|
|
23756
|
-
const { betas, ...
|
|
23756
|
+
const { betas, ...query2 } = params ?? {};
|
|
23757
23757
|
return this._client.getAPIList("/v1/models", Page, {
|
|
23758
|
-
query,
|
|
23758
|
+
query: query2,
|
|
23759
23759
|
...options,
|
|
23760
23760
|
headers: buildHeaders([
|
|
23761
23761
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -24104,8 +24104,8 @@ var init_client = __esm({
|
|
|
24104
24104
|
}
|
|
24105
24105
|
return buildHeaders([{ Authorization: `Bearer ${this.authToken}` }]);
|
|
24106
24106
|
}
|
|
24107
|
-
stringifyQuery(
|
|
24108
|
-
return stringifyQuery(
|
|
24107
|
+
stringifyQuery(query2) {
|
|
24108
|
+
return stringifyQuery(query2);
|
|
24109
24109
|
}
|
|
24110
24110
|
getUserAgent() {
|
|
24111
24111
|
return `${this.constructor.name}/JS ${VERSION}`;
|
|
@@ -24116,16 +24116,16 @@ var init_client = __esm({
|
|
|
24116
24116
|
makeStatusError(status, error2, message, headers) {
|
|
24117
24117
|
return APIError.generate(status, error2, message, headers);
|
|
24118
24118
|
}
|
|
24119
|
-
buildURL(path5,
|
|
24119
|
+
buildURL(path5, query2, defaultBaseURL) {
|
|
24120
24120
|
const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
24121
24121
|
const url = isAbsoluteURL(path5) ? new URL(path5) : new URL(baseURL + (baseURL.endsWith("/") && path5.startsWith("/") ? path5.slice(1) : path5));
|
|
24122
24122
|
const defaultQuery = this.defaultQuery();
|
|
24123
24123
|
const pathQuery = Object.fromEntries(url.searchParams);
|
|
24124
24124
|
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
|
|
24125
|
-
|
|
24125
|
+
query2 = { ...pathQuery, ...defaultQuery, ...query2 };
|
|
24126
24126
|
}
|
|
24127
|
-
if (typeof
|
|
24128
|
-
url.search = this.stringifyQuery(
|
|
24127
|
+
if (typeof query2 === "object" && query2 && !Array.isArray(query2)) {
|
|
24128
|
+
url.search = this.stringifyQuery(query2);
|
|
24129
24129
|
}
|
|
24130
24130
|
return url.toString();
|
|
24131
24131
|
}
|
|
@@ -24438,14 +24438,14 @@ var init_client = __esm({
|
|
|
24438
24438
|
}
|
|
24439
24439
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
24440
24440
|
const options = { ...inputOptions };
|
|
24441
|
-
const { method, path: path5, query, defaultBaseURL } = options;
|
|
24441
|
+
const { method, path: path5, query: query2, defaultBaseURL } = options;
|
|
24442
24442
|
if (this._authState.resolution) {
|
|
24443
24443
|
await this._authState.resolution;
|
|
24444
24444
|
}
|
|
24445
24445
|
if (!this._baseURLIsExplicit && this._authState.baseURL && this.baseURL !== this._authState.baseURL) {
|
|
24446
24446
|
this.baseURL = this._authState.baseURL;
|
|
24447
24447
|
}
|
|
24448
|
-
const url = this.buildURL(path5,
|
|
24448
|
+
const url = this.buildURL(path5, query2, defaultBaseURL);
|
|
24449
24449
|
if ("timeout" in options)
|
|
24450
24450
|
validatePositiveInteger("timeout", options.timeout);
|
|
24451
24451
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -24563,8 +24563,8 @@ function stripFallbackBlocks(body) {
|
|
|
24563
24563
|
function betaRefusalFallbackMiddleware(fallbacks, options = {}) {
|
|
24564
24564
|
let warnedMissingState = false;
|
|
24565
24565
|
return async (request, next, ctx) => {
|
|
24566
|
-
const [path5,
|
|
24567
|
-
if (fallbacks.length === 0 || ctx.options?.method !== "post" || path5 !== "/v1/messages" || new URLSearchParams(
|
|
24566
|
+
const [path5, query2] = (ctx.options?.path ?? "").split("?");
|
|
24567
|
+
if (fallbacks.length === 0 || ctx.options?.method !== "post" || path5 !== "/v1/messages" || new URLSearchParams(query2).get("beta") !== "true" || typeof ctx.options.body !== "object" || ctx.options.body == null) {
|
|
24568
24568
|
return next(request);
|
|
24569
24569
|
}
|
|
24570
24570
|
if (ctx.options.body.fallbacks != null) {
|
|
@@ -26568,7 +26568,7 @@ ${facts.stderr}`))
|
|
|
26568
26568
|
return null;
|
|
26569
26569
|
}
|
|
26570
26570
|
function isCommandUnavailable(facts, countsRead) {
|
|
26571
|
-
if (facts.exitCode === 127 || facts.exitCode === 126)
|
|
26571
|
+
if (facts.exitCode === 127 || facts.exitCode === 126 || facts.exitCode === 125)
|
|
26572
26572
|
return true;
|
|
26573
26573
|
if (countsRead)
|
|
26574
26574
|
return false;
|
|
@@ -26576,6 +26576,22 @@ function isCommandUnavailable(facts, countsRead) {
|
|
|
26576
26576
|
return false;
|
|
26577
26577
|
return facts.stdout.trim().length === 0 && EXEC_FAILURE.test(facts.stderr);
|
|
26578
26578
|
}
|
|
26579
|
+
function isOfflineBuildGap(facts, counts) {
|
|
26580
|
+
if (facts.runtime !== "jvm")
|
|
26581
|
+
return null;
|
|
26582
|
+
if (counts !== null && counts.tests_failed > 0)
|
|
26583
|
+
return null;
|
|
26584
|
+
if (facts.exitCode === 0 || facts.exitCode === null)
|
|
26585
|
+
return null;
|
|
26586
|
+
const out = `${facts.stdout}
|
|
26587
|
+
${facts.stderr}`;
|
|
26588
|
+
for (const pattern of OFFLINE_BUILD_GAP) {
|
|
26589
|
+
const hit = pattern.exec(out);
|
|
26590
|
+
if (hit)
|
|
26591
|
+
return hit[0];
|
|
26592
|
+
}
|
|
26593
|
+
return null;
|
|
26594
|
+
}
|
|
26579
26595
|
function classifyVerification(facts) {
|
|
26580
26596
|
if (facts.timedOut) {
|
|
26581
26597
|
return {
|
|
@@ -26600,6 +26616,14 @@ function classifyVerification(facts) {
|
|
|
26600
26616
|
reason: `the test command could not be invoked (exit ${String(facts.exitCode)}). This is an environment failure on our side \u2014 a missing interpreter, a binary outside PATH, or a dependency installed somewhere the command cannot see it. The repo has not been judged.`
|
|
26601
26617
|
};
|
|
26602
26618
|
}
|
|
26619
|
+
const gap = isOfflineBuildGap(facts, counts);
|
|
26620
|
+
if (gap !== null) {
|
|
26621
|
+
return {
|
|
26622
|
+
outcome: "test-command-unavailable",
|
|
26623
|
+
counts,
|
|
26624
|
+
reason: `the build stopped on something our install step did not fetch (${gap}). The test step has no network, so this is a gap in our environment, not a failure in the repo. The repo has not been judged.`
|
|
26625
|
+
};
|
|
26626
|
+
}
|
|
26603
26627
|
if (counts !== null) {
|
|
26604
26628
|
if (counts.tests_failed > 0) {
|
|
26605
26629
|
return {
|
|
@@ -26654,10 +26678,19 @@ function isGreen(outcome) {
|
|
|
26654
26678
|
function isOurFault(outcome) {
|
|
26655
26679
|
return outcome === "test-command-unavailable" || outcome === "counts-unparsed";
|
|
26656
26680
|
}
|
|
26657
|
-
var int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE;
|
|
26681
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, OFFLINE_BUILD_GAP;
|
|
26658
26682
|
var init_classify2 = __esm({
|
|
26659
26683
|
"../../packages/envrun/dist/classify.js"() {
|
|
26660
26684
|
"use strict";
|
|
26685
|
+
VERIFICATION_OUTCOMES = [
|
|
26686
|
+
"completed",
|
|
26687
|
+
"tests-failed",
|
|
26688
|
+
"no-tests-observed",
|
|
26689
|
+
"counts-unparsed",
|
|
26690
|
+
"test-command-unavailable",
|
|
26691
|
+
"environment-exhausted",
|
|
26692
|
+
"budget-exceeded"
|
|
26693
|
+
];
|
|
26661
26694
|
int = (m, i = 1) => m ? Number(m[i]) : 0;
|
|
26662
26695
|
withSuiteFailures = (counts, suiteLine) => {
|
|
26663
26696
|
if (counts.tests_failed > 0 || !suiteLine)
|
|
@@ -26757,6 +26790,51 @@ var init_classify2 = __esm({
|
|
|
26757
26790
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
26758
26791
|
}
|
|
26759
26792
|
},
|
|
26793
|
+
{
|
|
26794
|
+
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
26795
|
+
// 3.2.5 through `th run`:
|
|
26796
|
+
//
|
|
26797
|
+
// [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
|
|
26798
|
+
//
|
|
26799
|
+
// The per-CLASS lines carry the same counts followed by `, Time elapsed: …`, so
|
|
26800
|
+
// the end anchor after `Skipped` is what keeps them out; counting both would
|
|
26801
|
+
// double every test. One summary prints per module, so they are SUMMED. An
|
|
26802
|
+
// error is a test that could not run to an assertion, counted as failed so a
|
|
26803
|
+
// green verdict is impossible while one is outstanding, as pytest's are.
|
|
26804
|
+
runner: "maven surefire",
|
|
26805
|
+
read: (out) => {
|
|
26806
|
+
const lines = [
|
|
26807
|
+
...out.matchAll(/^(?:\[(?:INFO|WARNING|ERROR)\] )?Tests run: (\d+), Failures: (\d+), Errors: (\d+), Skipped: (\d+)(?:, Flakes: \d+)?\s*$/gm)
|
|
26808
|
+
];
|
|
26809
|
+
if (lines.length === 0)
|
|
26810
|
+
return null;
|
|
26811
|
+
let passed = 0;
|
|
26812
|
+
let failed = 0;
|
|
26813
|
+
for (const m of lines) {
|
|
26814
|
+
const [run3, failures, errors, skipped] = [m[1], m[2], m[3], m[4]].map(Number);
|
|
26815
|
+
failed += failures + errors;
|
|
26816
|
+
passed += Math.max(0, run3 - failures - errors - skipped);
|
|
26817
|
+
}
|
|
26818
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
26819
|
+
}
|
|
26820
|
+
},
|
|
26821
|
+
{
|
|
26822
|
+
// Gradle prints no test counts when every test passes, so envrun installs an
|
|
26823
|
+
// init script that prints one line per Test task (`gradleTestSummary.ts`,
|
|
26824
|
+
// TERM-1122). The marker is ours; its format is fixed there.
|
|
26825
|
+
runner: "gradle",
|
|
26826
|
+
read: (out) => {
|
|
26827
|
+
const lines = [
|
|
26828
|
+
...out.matchAll(/^terminalhire-gradle-tests: task=\S+ total=(\d+) passed=(\d+) failed=(\d+) skipped=(\d+)\s*$/gm)
|
|
26829
|
+
];
|
|
26830
|
+
if (lines.length === 0)
|
|
26831
|
+
return null;
|
|
26832
|
+
return {
|
|
26833
|
+
tests_passed: lines.reduce((sum, m) => sum + Number(m[2]), 0),
|
|
26834
|
+
tests_failed: lines.reduce((sum, m) => sum + Number(m[3]), 0)
|
|
26835
|
+
};
|
|
26836
|
+
}
|
|
26837
|
+
},
|
|
26760
26838
|
{
|
|
26761
26839
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
26762
26840
|
runner: "mocha",
|
|
@@ -26791,6 +26869,79 @@ var init_classify2 = __esm({
|
|
|
26791
26869
|
const p = int(passed);
|
|
26792
26870
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
26793
26871
|
}
|
|
26872
|
+
},
|
|
26873
|
+
{
|
|
26874
|
+
/**
|
|
26875
|
+
* BARE TAP — assertion lines with no plan and no summary comment (TERM-1138).
|
|
26876
|
+
*
|
|
26877
|
+
* LAST ON PURPOSE. It is the loosest reader here, so anything that a more specific
|
|
26878
|
+
* one can read must reach that one first: `node --test` and node-tap both emit `ok`
|
|
26879
|
+
* lines AND a closing summary, and their readers are ordered above for that reason.
|
|
26880
|
+
* Moving this up would have it answer for both.
|
|
26881
|
+
*
|
|
26882
|
+
* A hand-rolled harness prints neither summary — it emits its assertions and stops.
|
|
26883
|
+
* That is what morebetterltd/wheelhouse does: thirty `ok N - …` lines, exit 0, and
|
|
26884
|
+
* before this every one of those runs reported `counts-unparsed`, which the claim
|
|
26885
|
+
* page renders as "RESULT UNREADABLE — THE SUITE EXITED 0" over a suite that passed.
|
|
26886
|
+
*
|
|
26887
|
+
* ON THE MISSING PLAN LINE. TAP requires `1..N` so a reader can tell a finished
|
|
26888
|
+
* stream from a truncated one, and there is none here, so this cannot prove the
|
|
26889
|
+
* suite reached its end. That is a real limit and it is NOT a reason to refuse,
|
|
26890
|
+
* because it holds this format to a standard no reader in this file meets — the
|
|
26891
|
+
* jest reader greps a line out of stdout that a repository could `echo` without
|
|
26892
|
+
* running anything. These are format adapters, not a trust boundary; the boundary
|
|
26893
|
+
* is that the command is the repository's own or is refused a signature.
|
|
26894
|
+
*
|
|
26895
|
+
* CONTIGUOUS FROM 1, which buys self-consistency rather than security:
|
|
26896
|
+
*
|
|
26897
|
+
* - starting at 1 rejects a TRUNCATION. `testOutputTail` keeps the last lines, so
|
|
26898
|
+
* a stream beginning `ok 47` is the middle of a longer run and counting it would
|
|
26899
|
+
* report three tests for a suite that ran fifty.
|
|
26900
|
+
* - no gaps rejects prose that happens to carry the word, and a stream interleaved
|
|
26901
|
+
* with another's.
|
|
26902
|
+
* - anchored with no leading space rejects TAP SUBTESTS, which indent. Counting
|
|
26903
|
+
* those would double them against their parent.
|
|
26904
|
+
*/
|
|
26905
|
+
runner: "bare TAP",
|
|
26906
|
+
read: (out) => {
|
|
26907
|
+
let n = 0;
|
|
26908
|
+
let failed = 0;
|
|
26909
|
+
let passed = 0;
|
|
26910
|
+
let plan = null;
|
|
26911
|
+
for (const line of out.split("\n")) {
|
|
26912
|
+
if (/^Bail out!/.test(line))
|
|
26913
|
+
return null;
|
|
26914
|
+
const p = /^(\d+)\.\.(\d+)\s*$/.exec(line);
|
|
26915
|
+
if (p) {
|
|
26916
|
+
const declared = Number(p[2]) - Number(p[1]) + 1;
|
|
26917
|
+
if (plan !== null && plan !== declared)
|
|
26918
|
+
return null;
|
|
26919
|
+
plan = declared;
|
|
26920
|
+
continue;
|
|
26921
|
+
}
|
|
26922
|
+
const m = /^(not )?ok (\d+)(?:\s|$)/.exec(line);
|
|
26923
|
+
if (!m)
|
|
26924
|
+
continue;
|
|
26925
|
+
if (Number(m[2]) !== n + 1)
|
|
26926
|
+
return null;
|
|
26927
|
+
n += 1;
|
|
26928
|
+
const directive = /#\s*(skip|todo)\b/i.exec(line);
|
|
26929
|
+
const kind = directive?.[1]?.toLowerCase();
|
|
26930
|
+
if (kind === "skip")
|
|
26931
|
+
continue;
|
|
26932
|
+
if (m[1] !== void 0) {
|
|
26933
|
+
if (kind !== "todo")
|
|
26934
|
+
failed += 1;
|
|
26935
|
+
continue;
|
|
26936
|
+
}
|
|
26937
|
+
passed += 1;
|
|
26938
|
+
}
|
|
26939
|
+
if (n === 0)
|
|
26940
|
+
return null;
|
|
26941
|
+
if (plan !== null && plan !== n)
|
|
26942
|
+
return null;
|
|
26943
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
26944
|
+
}
|
|
26794
26945
|
}
|
|
26795
26946
|
];
|
|
26796
26947
|
SUPPORTED_RUNNERS = READERS.map((r) => r.runner);
|
|
@@ -26812,6 +26963,21 @@ var init_classify2 = __esm({
|
|
|
26812
26963
|
"\\d+\\s+examples?,\\s+(?!0\\b)\\d+\\s+failures?"
|
|
26813
26964
|
// rspec's summary line
|
|
26814
26965
|
].join("|"), "m");
|
|
26966
|
+
OFFLINE_BUILD_GAP = [
|
|
26967
|
+
// Maven, `-o`: `Cannot access central (…) in offline mode and the artifact … has
|
|
26968
|
+
// not been downloaded from it before.`
|
|
26969
|
+
/in offline mode and the artifact \S+ has not been downloaded from it before/,
|
|
26970
|
+
// Maven without `-o`, as a CI-derived `mvn test` runs: it tries the network.
|
|
26971
|
+
/Could not transfer artifact \S+ from\/to /,
|
|
26972
|
+
/Plugin \S+ or one of its dependencies could not be resolved/,
|
|
26973
|
+
// Gradle, `--offline`.
|
|
26974
|
+
/No cached version (?:listing )?(?:of|for) \S+ available for offline mode/,
|
|
26975
|
+
// Gradle without `--offline`, and the wrapper fetching its own distribution.
|
|
26976
|
+
/Could not GET 'https?:\/\//,
|
|
26977
|
+
/^Downloading https:\/\/services\.gradle\.org\/distributions\//m,
|
|
26978
|
+
/No matching toolchains found for requested specification/,
|
|
26979
|
+
/Cannot find a Java installation on your machine matching/
|
|
26980
|
+
];
|
|
26815
26981
|
}
|
|
26816
26982
|
});
|
|
26817
26983
|
|
|
@@ -26877,6 +27043,12 @@ function scrubEnv(source, opts) {
|
|
|
26877
27043
|
env["GOCACHE"] = join20(jailHome, ".cache", "go-build");
|
|
26878
27044
|
env["GOFLAGS"] = "-modcacherw";
|
|
26879
27045
|
env["CARGO_HOME"] = join20(jailHome, ".cargo");
|
|
27046
|
+
env["MAVEN_OPTS"] = `-Dmaven.repo.local=${join20(jailHome, ".m2", "repository")}`;
|
|
27047
|
+
env["GRADLE_USER_HOME"] = join20(jailHome, ".gradle");
|
|
27048
|
+
const bundle = join20(jailHome, ".bundle");
|
|
27049
|
+
env["GEM_HOME"] = bundle;
|
|
27050
|
+
env["BUNDLE_PATH"] = bundle;
|
|
27051
|
+
env["BUNDLE_APP_CONFIG"] = bundle;
|
|
26880
27052
|
const proxy = opts.proxyUrl ?? DEAD_PROXY;
|
|
26881
27053
|
env["HTTP_PROXY"] = proxy;
|
|
26882
27054
|
env["HTTPS_PROXY"] = proxy;
|
|
@@ -27177,6 +27349,31 @@ var init_egressProxy = __esm({
|
|
|
27177
27349
|
"static.crates.io",
|
|
27178
27350
|
"index.crates.io",
|
|
27179
27351
|
"crates.io",
|
|
27352
|
+
// TERM-1139. `ruby` has had an image since the mapping existed and `bundle install`
|
|
27353
|
+
// as its derived command, and this host was missing — so every ruby repo could start
|
|
27354
|
+
// and could never install. Install is the ONLY step with a network grant at all, so a
|
|
27355
|
+
// denial here is terminal, not a slow path.
|
|
27356
|
+
//
|
|
27357
|
+
// One entry, not two: `hostAllowed` is dot-anchored SUFFIX matching, so this covers
|
|
27358
|
+
// `index.rubygems.org` as well. Listing that separately would advertise the grant as
|
|
27359
|
+
// narrower than it is, which the `github.com` note below rejects for the same reason.
|
|
27360
|
+
"rubygems.org",
|
|
27361
|
+
// TERM-1139, added with the `dotnet` image mapping. `dotnet restore` fetches from
|
|
27362
|
+
// NuGet; the coupling test refuses a mapped runtime whose registry is unreachable, and
|
|
27363
|
+
// it caught this one the moment the image landed.
|
|
27364
|
+
"api.nuget.org",
|
|
27365
|
+
// TERM-1122, added with the `jvm` image mapping, each from a MEASURED denial
|
|
27366
|
+
// through `th run` (the proxy's 403 in the build's own output), not a guess:
|
|
27367
|
+
// - Maven Central, where both `mvn` and Gradle's `mavenCentral()` resolve.
|
|
27368
|
+
// - `services.gradle.org`, where a Gradle wrapper fetches its distribution.
|
|
27369
|
+
// - `release-assets.githubusercontent.com`, where that fetch LANDS. Measured
|
|
27370
|
+
// chain: services.gradle.org 307 -> github.com 302 -> this host 200. The
|
|
27371
|
+
// `github.com` note below keeps `githubusercontent.com` denied until a real
|
|
27372
|
+
// install needs it; this is that install. Only this one host: raw blobs and
|
|
27373
|
+
// `objects.githubusercontent.com` stay denied.
|
|
27374
|
+
"repo.maven.apache.org",
|
|
27375
|
+
"services.gradle.org",
|
|
27376
|
+
"release-assets.githubusercontent.com",
|
|
27180
27377
|
// Git dependencies. Approved by Eric 2026-07-22 after a live run measured the
|
|
27181
27378
|
// chokepoint working under load (20 events, 16 allowed / 4 denied by host).
|
|
27182
27379
|
//
|
|
@@ -27468,6 +27665,9 @@ function containerArgs(spec, env, opts) {
|
|
|
27468
27665
|
args.push(`--env=${k}=${url}`);
|
|
27469
27666
|
}
|
|
27470
27667
|
args.push("--env=NO_PROXY=", "--env=no_proxy=");
|
|
27668
|
+
const host = opts.net.proxyHost;
|
|
27669
|
+
const port = String(opts.net.proxyPort);
|
|
27670
|
+
args.push(`--env=JAVA_TOOL_OPTIONS=-Dhttp.proxyHost=${host} -Dhttp.proxyPort=${port} -Dhttps.proxyHost=${host} -Dhttps.proxyPort=${port} -Daether.connector.http.useSystemProperties=true`);
|
|
27471
27671
|
}
|
|
27472
27672
|
args.push("--");
|
|
27473
27673
|
args.push(validateImage(opts.image ?? DEFAULT_CONTAINER_IMAGE));
|
|
@@ -27800,7 +28000,10 @@ var init_container = __esm({
|
|
|
27800
28000
|
"http_proxy",
|
|
27801
28001
|
"https_proxy",
|
|
27802
28002
|
"NO_PROXY",
|
|
27803
|
-
"no_proxy"
|
|
28003
|
+
"no_proxy",
|
|
28004
|
+
// Carries the JVM's copy of the proxy (below), so an inherited value is dropped
|
|
28005
|
+
// for the same reason as the rest.
|
|
28006
|
+
"JAVA_TOOL_OPTIONS"
|
|
27804
28007
|
]);
|
|
27805
28008
|
WINDOWS_DRIVE_ROOT = /^[A-Za-z]:[\\/]/;
|
|
27806
28009
|
IMAGE_HOST = "(?:[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)+(?::[0-9]+)?|localhost(?::[0-9]+)?)";
|
|
@@ -27850,11 +28053,17 @@ var init_dist = __esm({
|
|
|
27850
28053
|
function censusTotal(c) {
|
|
27851
28054
|
return c.containers.length + c.volumes.length + c.networks.length;
|
|
27852
28055
|
}
|
|
27853
|
-
function
|
|
28056
|
+
function query(docker3, args) {
|
|
27854
28057
|
const res = docker3.sync([...args], { timeoutMs: 15e3 });
|
|
27855
|
-
if (res.error || res.status !== 0)
|
|
27856
|
-
|
|
27857
|
-
|
|
28058
|
+
if (res.error || res.status !== 0) {
|
|
28059
|
+
const why = res.error?.message ?? (res.stderr.trim() || `exit ${String(res.status)}`);
|
|
28060
|
+
return { ids: [], failure: `docker ${args.slice(0, 2).join(" ")}: ${why}` };
|
|
28061
|
+
}
|
|
28062
|
+
const ids2 = res.stdout.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
28063
|
+
return { ids: ids2, failure: null };
|
|
28064
|
+
}
|
|
28065
|
+
function ids(docker3, args) {
|
|
28066
|
+
return query(docker3, args).ids;
|
|
27858
28067
|
}
|
|
27859
28068
|
function census(docker3, label) {
|
|
27860
28069
|
const filter = `label=${label}`;
|
|
@@ -27864,25 +28073,67 @@ function census(docker3, label) {
|
|
|
27864
28073
|
networks: ids(docker3, ["network", "ls", "-q", "--filter", filter])
|
|
27865
28074
|
};
|
|
27866
28075
|
}
|
|
28076
|
+
function censusReport(docker3, label) {
|
|
28077
|
+
const filter = `label=${label}`;
|
|
28078
|
+
const failures = [];
|
|
28079
|
+
const ask2 = (args) => {
|
|
28080
|
+
const q = query(docker3, args);
|
|
28081
|
+
if (q.failure !== null)
|
|
28082
|
+
failures.push(q.failure);
|
|
28083
|
+
return q.ids;
|
|
28084
|
+
};
|
|
28085
|
+
const taken = {
|
|
28086
|
+
containers: ask2(["ps", "-aq", "--filter", filter]),
|
|
28087
|
+
volumes: ask2(["volume", "ls", "-q", "--filter", filter]),
|
|
28088
|
+
networks: ask2(["network", "ls", "-q", "--filter", filter])
|
|
28089
|
+
};
|
|
28090
|
+
return failures.length === 0 ? { observed: true, census: taken, unobservedReason: null } : { observed: false, census: taken, unobservedReason: failures.join("; ") };
|
|
28091
|
+
}
|
|
27867
28092
|
function localCensus(label) {
|
|
27868
28093
|
return census(localDockerClient(), label);
|
|
27869
28094
|
}
|
|
27870
|
-
function judgeLeaks(peak, after) {
|
|
28095
|
+
function judgeLeaks(peak, after, observation) {
|
|
27871
28096
|
const labelObserved = peak.containers.length > 0;
|
|
28097
|
+
if (!observation.observed) {
|
|
28098
|
+
return {
|
|
28099
|
+
labelObserved,
|
|
28100
|
+
reaped: false,
|
|
28101
|
+
observed: false,
|
|
28102
|
+
clean: false,
|
|
28103
|
+
state: "unobserved",
|
|
28104
|
+
peak,
|
|
28105
|
+
after,
|
|
28106
|
+
note: `UNOBSERVED, not clean: we could not look at what survived teardown (${observation.unobservedReason ?? "no reason given"}), so nothing is known about leaks on this run, in either direction.`
|
|
28107
|
+
};
|
|
28108
|
+
}
|
|
27872
28109
|
const reaped = censusTotal(after) === 0;
|
|
27873
28110
|
let note;
|
|
28111
|
+
let state;
|
|
27874
28112
|
if (!labelObserved && reaped) {
|
|
28113
|
+
state = "inconclusive";
|
|
27875
28114
|
note = "INCONCLUSIVE, not clean: nothing labelled was ever seen alive, so an empty final census is equally consistent with the label never being applied. The control failed, so the denial proves nothing.";
|
|
27876
28115
|
} else if (!labelObserved) {
|
|
28116
|
+
state = "leak";
|
|
27877
28117
|
note = "no labelled container was observed alive AND objects remain \u2014 the label wiring is wrong.";
|
|
27878
28118
|
} else if (!reaped) {
|
|
28119
|
+
state = "leak";
|
|
27879
28120
|
note = `LEAK: ${String(censusTotal(after))} labelled object(s) survived teardown (containers=${String(after.containers.length)} volumes=${String(after.volumes.length)} networks=${String(after.networks.length)}).`;
|
|
27880
28121
|
} else {
|
|
28122
|
+
state = "clean";
|
|
27881
28123
|
note = `clean: peak ${String(peak.containers.length)} labelled container(s) observed alive, 0 labelled objects remain after teardown.`;
|
|
27882
28124
|
}
|
|
27883
|
-
return {
|
|
28125
|
+
return {
|
|
28126
|
+
labelObserved,
|
|
28127
|
+
reaped,
|
|
28128
|
+
observed: true,
|
|
28129
|
+
clean: labelObserved && reaped,
|
|
28130
|
+
state,
|
|
28131
|
+
peak,
|
|
28132
|
+
after,
|
|
28133
|
+
note
|
|
28134
|
+
};
|
|
27884
28135
|
}
|
|
27885
|
-
var RUN_LABEL_KEY, LabelWatch;
|
|
28136
|
+
var RUN_LABEL_KEY, LabelWatch, LEAK_STATES;
|
|
27886
28137
|
var init_labels = __esm({
|
|
27887
28138
|
"../../packages/envrun/dist/labels.js"() {
|
|
27888
28139
|
"use strict";
|
|
@@ -27937,6 +28188,7 @@ var init_labels = __esm({
|
|
|
27937
28188
|
return this.#samples;
|
|
27938
28189
|
}
|
|
27939
28190
|
};
|
|
28191
|
+
LEAK_STATES = ["clean", "leak", "inconclusive", "unobserved"];
|
|
27940
28192
|
}
|
|
27941
28193
|
});
|
|
27942
28194
|
|
|
@@ -28421,7 +28673,7 @@ function acquireLocalLease(runId) {
|
|
|
28421
28673
|
observed: false,
|
|
28422
28674
|
census: { containers: [], volumes: [], networks: [] },
|
|
28423
28675
|
unobservedReason: RELEASED_LEASE_CENSUS_REASON
|
|
28424
|
-
} :
|
|
28676
|
+
} : censusReport(docker3, label)),
|
|
28425
28677
|
publishPreview: (req) => startPreview({ ...req, docker: docker3 }),
|
|
28426
28678
|
release: () => {
|
|
28427
28679
|
if (released) {
|
|
@@ -28541,6 +28793,17 @@ caused by: ${frame}`;
|
|
|
28541
28793
|
}
|
|
28542
28794
|
return frames === 0 ? null : out;
|
|
28543
28795
|
}
|
|
28796
|
+
function imageVariantFor(spec) {
|
|
28797
|
+
if (spec.runtime !== "jvm")
|
|
28798
|
+
return void 0;
|
|
28799
|
+
const callsGradle = /(?:^|[\s;&|(])gradle(?=\s|$)/;
|
|
28800
|
+
return [spec.installCommand, spec.testCommand].some((c) => c != null && callsGradle.test(c)) ? "gradle" : void 0;
|
|
28801
|
+
}
|
|
28802
|
+
function shapeFor(runtime, variant) {
|
|
28803
|
+
if (runtime === "jvm" && variant === "gradle")
|
|
28804
|
+
return JVM_GRADLE_IMAGE;
|
|
28805
|
+
return RUNTIME_IMAGES[runtime];
|
|
28806
|
+
}
|
|
28544
28807
|
function atLeast(a, b) {
|
|
28545
28808
|
const left = a.split(".").map(Number);
|
|
28546
28809
|
const right = b.split(".").map(Number);
|
|
@@ -28553,19 +28816,19 @@ function atLeast(a, b) {
|
|
|
28553
28816
|
}
|
|
28554
28817
|
return true;
|
|
28555
28818
|
}
|
|
28556
|
-
function imageForRuntime(runtime, override, version2) {
|
|
28819
|
+
function imageForRuntime(runtime, override, version2, variant) {
|
|
28557
28820
|
if (override)
|
|
28558
28821
|
return override;
|
|
28559
|
-
const shape =
|
|
28822
|
+
const shape = shapeFor(runtime, variant);
|
|
28560
28823
|
if (!shape) {
|
|
28561
|
-
throw new RunRefusalError(`no container image is mapped for runtime ${JSON.stringify(runtime)}. Refusing to run it in the Node image: a
|
|
28824
|
+
throw new RunRefusalError(`no container image is mapped for runtime ${JSON.stringify(runtime)}. Refusing to run it in the Node image: a bare "command not found" exits 127, which classifyVerification already owns as ours \u2014 but a test script that RUNS and fails inside on the missing tool exits with its own status and prints to stdout, and that falls through to tests-failed \u2014 a false red blamed on the repo.`);
|
|
28562
28825
|
}
|
|
28563
28826
|
if (version2 === void 0 || version2 === null)
|
|
28564
28827
|
return unversionedImage(shape);
|
|
28565
28828
|
if (!TAG_VERSION.test(version2)) {
|
|
28566
28829
|
throw new RunRefusalError(`runtime version ${JSON.stringify(version2)} is not a bare version, so no image tag can be built from it. Refusing rather than booting the default: the repo asked for a version, and supplying a different one silently is what TERM-643 fixed.`);
|
|
28567
28830
|
}
|
|
28568
|
-
return `${shape.repository}:${version2}${shape.suffix}`;
|
|
28831
|
+
return `${shape.repository}:${shape.prefix ?? ""}${version2}${shape.suffix}`;
|
|
28569
28832
|
}
|
|
28570
28833
|
function setManifestProbe(probe) {
|
|
28571
28834
|
const previous = manifestProbe;
|
|
@@ -28578,10 +28841,10 @@ function imageDefinitelyAbsent(image) {
|
|
|
28578
28841
|
return false;
|
|
28579
28842
|
return /manifest unknown|no such manifest/i.test(res.output);
|
|
28580
28843
|
}
|
|
28581
|
-
function resolvePublishedImage(image, runtime, version2) {
|
|
28844
|
+
function resolvePublishedImage(image, runtime, version2, variant) {
|
|
28582
28845
|
if (!imageDefinitelyAbsent(image))
|
|
28583
28846
|
return image;
|
|
28584
|
-
const shape =
|
|
28847
|
+
const shape = shapeFor(runtime, variant);
|
|
28585
28848
|
if (shape && shape.declaredIsFloor && atLeast(shape.defaultVersion, version2)) {
|
|
28586
28849
|
return unversionedImage(shape);
|
|
28587
28850
|
}
|
|
@@ -28589,18 +28852,19 @@ function resolvePublishedImage(image, runtime, version2) {
|
|
|
28589
28852
|
}
|
|
28590
28853
|
function resolveImageForSpec(spec, override) {
|
|
28591
28854
|
const declared = spec.runtimeVersion;
|
|
28592
|
-
const
|
|
28855
|
+
const variant = imageVariantFor(spec);
|
|
28856
|
+
const image = imageForRuntime(spec.runtime, override, declared, variant);
|
|
28593
28857
|
const constructed = (() => {
|
|
28594
28858
|
if (declared === null)
|
|
28595
28859
|
return null;
|
|
28596
28860
|
try {
|
|
28597
|
-
return imageForRuntime(spec.runtime, void 0, declared);
|
|
28861
|
+
return imageForRuntime(spec.runtime, void 0, declared, variant);
|
|
28598
28862
|
} catch {
|
|
28599
28863
|
return null;
|
|
28600
28864
|
}
|
|
28601
28865
|
})();
|
|
28602
28866
|
if (constructed !== null && image === constructed && declared !== null) {
|
|
28603
|
-
return resolvePublishedImage(image, spec.runtime, declared);
|
|
28867
|
+
return resolvePublishedImage(image, spec.runtime, declared, variant);
|
|
28604
28868
|
}
|
|
28605
28869
|
return image;
|
|
28606
28870
|
}
|
|
@@ -28627,12 +28891,22 @@ function assertVenueOwnerDeclared(lease) {
|
|
|
28627
28891
|
return;
|
|
28628
28892
|
throw new RunRefusalError("this venue did not say which account owns the tree it staged, so the guest would run under this machine's uid and could not write its own clone. We refuse rather than report that permission error as the repo's tests failing.");
|
|
28629
28893
|
}
|
|
28894
|
+
function refuseUnbuildableSpec(spec) {
|
|
28895
|
+
if (spec.runtime !== "jvm" || spec.installCommand !== null || spec.testCommand !== null)
|
|
28896
|
+
return;
|
|
28897
|
+
const why = spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
28898
|
+
if (why === void 0) {
|
|
28899
|
+
throw new EnvRunError("internal: a jvm spec with no test command carries no no-test-command reason");
|
|
28900
|
+
}
|
|
28901
|
+
throw new RunRefusalError(`refusing to run this repository: ${why}.`);
|
|
28902
|
+
}
|
|
28630
28903
|
async function runEnvironmentSpec(req) {
|
|
28631
28904
|
const startedAt = Date.now();
|
|
28632
28905
|
const containment = req.lease.containment;
|
|
28633
28906
|
if (containment.kind !== "container") {
|
|
28634
28907
|
throw new EnvRunError(`phase 2 requires the container tier, got ${containment.kind}. Refusing: a container phase that silently ran under seatbelt would make every container claim vacuous.`);
|
|
28635
28908
|
}
|
|
28909
|
+
refuseUnbuildableSpec(req.spec);
|
|
28636
28910
|
assertVenueOwnerDeclared(req.lease);
|
|
28637
28911
|
const image = resolveImageForSpec(req.spec, req.image);
|
|
28638
28912
|
const { jail, tmp } = req;
|
|
@@ -28675,9 +28949,10 @@ async function runEnvironmentSpec(req) {
|
|
|
28675
28949
|
installOk: false
|
|
28676
28950
|
};
|
|
28677
28951
|
} else if (req.spec.testCommand === null) {
|
|
28952
|
+
const why = req.spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
28678
28953
|
result = {
|
|
28679
28954
|
outcome: "no-tests-observed",
|
|
28680
|
-
note: "the spec derived no test command, so nothing was executed: nothing failed and nothing ran. Certain, not inferred \u2014 no command was ever invoked.",
|
|
28955
|
+
note: "the spec derived no test command, so nothing was executed: nothing failed and nothing ran. Certain, not inferred \u2014 no command was ever invoked." + (why === void 0 ? "" : ` Why: ${why}.`),
|
|
28681
28956
|
installOk: true
|
|
28682
28957
|
};
|
|
28683
28958
|
} else {
|
|
@@ -28700,7 +28975,7 @@ async function runEnvironmentSpec(req) {
|
|
|
28700
28975
|
labels,
|
|
28701
28976
|
timeoutMs: req.testTimeoutMs ?? 9e5
|
|
28702
28977
|
});
|
|
28703
|
-
const verdict = classifyVerification(toExecution(test));
|
|
28978
|
+
const verdict = classifyVerification({ ...toExecution(test), runtime: req.spec.runtime });
|
|
28704
28979
|
result = { outcome: verdict.outcome, note: verdict.reason, installOk: true };
|
|
28705
28980
|
}
|
|
28706
28981
|
} finally {
|
|
@@ -28714,6 +28989,10 @@ async function runEnvironmentSpec(req) {
|
|
|
28714
28989
|
volumes: [],
|
|
28715
28990
|
networks: []
|
|
28716
28991
|
};
|
|
28992
|
+
const observation = afterReport ?? {
|
|
28993
|
+
observed: false,
|
|
28994
|
+
unobservedReason: "the run carried no label, so there was nothing to count by"
|
|
28995
|
+
};
|
|
28717
28996
|
return {
|
|
28718
28997
|
outcome: result.outcome,
|
|
28719
28998
|
tier: "container",
|
|
@@ -28722,7 +29001,7 @@ async function runEnvironmentSpec(req) {
|
|
|
28722
29001
|
test,
|
|
28723
29002
|
installOk: result.installOk,
|
|
28724
29003
|
counts: test ? readCounts(test.stdout, test.stderr) : null,
|
|
28725
|
-
leaks: judgeLeaks(peak, after),
|
|
29004
|
+
leaks: judgeLeaks(peak, after, observation),
|
|
28726
29005
|
note: result.note,
|
|
28727
29006
|
wallMs: Date.now() - startedAt
|
|
28728
29007
|
};
|
|
@@ -28772,7 +29051,7 @@ async function runStep(containment, r) {
|
|
|
28772
29051
|
wallMs: Date.now() - startedAt
|
|
28773
29052
|
};
|
|
28774
29053
|
}
|
|
28775
|
-
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
29054
|
+
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, JVM_GRADLE_IMAGE, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
28776
29055
|
var init_execute = __esm({
|
|
28777
29056
|
"../../packages/envrun/dist/execute.js"() {
|
|
28778
29057
|
"use strict";
|
|
@@ -28809,9 +29088,66 @@ var init_execute = __esm({
|
|
|
28809
29088
|
},
|
|
28810
29089
|
go: { repository: "golang", suffix: "-bookworm", defaultVersion: "1.23", declaredIsFloor: true },
|
|
28811
29090
|
ruby: { repository: "ruby", suffix: "-bookworm", defaultVersion: "3.3", declaredIsFloor: false },
|
|
28812
|
-
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true }
|
|
28813
|
-
|
|
28814
|
-
|
|
29091
|
+
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true },
|
|
29092
|
+
/**
|
|
29093
|
+
* TERM-1139. `dotnet` was unmapped alongside `jvm`, and the recorded reason was that
|
|
29094
|
+
* neither had "a single obvious base image (gradle vs maven, sdk vs runtime)". That
|
|
29095
|
+
* reason holds for jvm and it does NOT hold here, which is why only this half moved.
|
|
29096
|
+
*
|
|
29097
|
+
* "sdk vs runtime" answers itself: the derived commands are `dotnet restore` and
|
|
29098
|
+
* `dotnet test`, and neither exists on the runtime image. There is no second build
|
|
29099
|
+
* tool competing for the slot the way maven and gradle compete for jvm's — and since
|
|
29100
|
+
* no official image carries both of those, jvm genuinely cannot be served by one key.
|
|
29101
|
+
*
|
|
29102
|
+
* MEASURED, not chosen by tag: `mcr.microsoft.com/dotnet/sdk:8.0` carries `git` and
|
|
29103
|
+
* `dotnet` (881MB). `git` is the property the whole `image-tooling-live` test exists
|
|
29104
|
+
* for, and `eclipse-temurin:21-jdk` was rejected here for lacking it.
|
|
29105
|
+
*
|
|
29106
|
+
* The tag shape fits without touching the builder: the SDK publishes a tag per
|
|
29107
|
+
* version, so `repository:VERSION` is a real image at every version envspec can
|
|
29108
|
+
* derive, with no suffix. That is NOT true of the maven images, where the leading
|
|
29109
|
+
* tag component is maven's version and Java's sits in the suffix.
|
|
29110
|
+
*
|
|
29111
|
+
* `declaredIsFloor` is true on the same reasoning as go and rust: an SDK builds
|
|
29112
|
+
* older target frameworks, so booting 8.0 for a repo asking 6.0 is the supported
|
|
29113
|
+
* case rather than a substitution. A repo asking for something NEWER than our
|
|
29114
|
+
* default still refuses, which is where TERM-643 put that line.
|
|
29115
|
+
*/
|
|
29116
|
+
dotnet: {
|
|
29117
|
+
repository: "mcr.microsoft.com/dotnet/sdk",
|
|
29118
|
+
suffix: "",
|
|
29119
|
+
defaultVersion: "8.0",
|
|
29120
|
+
declaredIsFloor: true
|
|
29121
|
+
},
|
|
29122
|
+
/**
|
|
29123
|
+
* TERM-1122. Maven's image, and the one a Gradle WRAPPER repo gets too: the wrapper
|
|
29124
|
+
* downloads its own Gradle, so it needs a JDK and nothing else. MEASURED
|
|
29125
|
+
* 2026-09-18: `maven:3.9-eclipse-temurin-21` carries `git`, `mvn` and JDK 21 on
|
|
29126
|
+
* Ubuntu 24.04, which is why this is not `eclipse-temurin` (no `git`, rejected
|
|
29127
|
+
* under TERM-1139). The JDK sits AFTER maven's own version in the tag, hence
|
|
29128
|
+
* `prefix`, and the major is all envspec derives (`javaMajor`).
|
|
29129
|
+
*
|
|
29130
|
+
* `declaredIsFloor`: a JDK builds for older `--release` targets, so a repo asking
|
|
29131
|
+
* for 16, which has no image, runs on 21. A Gradle toolchain is stricter than a
|
|
29132
|
+
* floor and asks for its exact JDK; Gradle's refusal on the wrong one reads as
|
|
29133
|
+
* ours (`classify.ts`, `isOfflineBuildGap`), never as the repo's.
|
|
29134
|
+
*/
|
|
29135
|
+
jvm: {
|
|
29136
|
+
repository: "maven",
|
|
29137
|
+
prefix: "3.9-eclipse-temurin-",
|
|
29138
|
+
suffix: "",
|
|
29139
|
+
defaultVersion: "21",
|
|
29140
|
+
declaredIsFloor: true
|
|
29141
|
+
}
|
|
29142
|
+
};
|
|
29143
|
+
JVM_GRADLE_IMAGE = {
|
|
29144
|
+
repository: "gradle",
|
|
29145
|
+
prefix: "jdk",
|
|
29146
|
+
suffix: "",
|
|
29147
|
+
defaultVersion: "21",
|
|
29148
|
+
declaredIsFloor: true
|
|
29149
|
+
};
|
|
29150
|
+
unversionedImage = (shape) => `${shape.repository}:${shape.prefix ?? ""}${shape.defaultVersion}${shape.suffix}`;
|
|
28815
29151
|
TAG_VERSION = /^\d+(?:\.\d+){0,2}$/;
|
|
28816
29152
|
dockerManifestProbe = (image) => {
|
|
28817
29153
|
const res = spawnSync4("docker", ["manifest", "inspect", image], {
|
|
@@ -29503,14 +29839,31 @@ function answerDidItPass(r) {
|
|
|
29503
29839
|
const passed = r.status === "verified" && r.outcome !== null && isGreen(r.outcome);
|
|
29504
29840
|
return { passed, summary: renderVerdictLine(r), lookAt: r.preview?.url ?? null };
|
|
29505
29841
|
}
|
|
29506
|
-
|
|
29842
|
+
function exitCodeFor(r) {
|
|
29843
|
+
if (r.status === "refused")
|
|
29844
|
+
return 2;
|
|
29845
|
+
if (r.outcome === null)
|
|
29846
|
+
return 2;
|
|
29847
|
+
return OUTCOME_EXIT_CODES[r.outcome];
|
|
29848
|
+
}
|
|
29849
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS, OUTCOME_EXIT_CODES;
|
|
29507
29850
|
var init_result = __esm({
|
|
29508
29851
|
"../../packages/envrun/dist/result.js"() {
|
|
29509
29852
|
"use strict";
|
|
29510
29853
|
init_dist2();
|
|
29511
29854
|
init_classify2();
|
|
29512
29855
|
init_venueDescriptor();
|
|
29513
|
-
RUN_TEST_COMMAND_SOURCES = [
|
|
29856
|
+
RUN_TEST_COMMAND_SOURCES = [
|
|
29857
|
+
...TEST_COMMAND_SOURCES,
|
|
29858
|
+
"developer-declared",
|
|
29859
|
+
"operator-declared"
|
|
29860
|
+
];
|
|
29861
|
+
RUN_IMAGE_SOURCES = [
|
|
29862
|
+
"detected",
|
|
29863
|
+
"none",
|
|
29864
|
+
"operator-declared",
|
|
29865
|
+
"developer-declared"
|
|
29866
|
+
];
|
|
29514
29867
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
29515
29868
|
RUN_RESULT_FIELDS = [
|
|
29516
29869
|
"schema",
|
|
@@ -29535,7 +29888,9 @@ var init_result = __esm({
|
|
|
29535
29888
|
"preview",
|
|
29536
29889
|
"containerImage",
|
|
29537
29890
|
"containerImageDigest",
|
|
29891
|
+
"imageSource",
|
|
29538
29892
|
"leaksClean",
|
|
29893
|
+
"leakState",
|
|
29539
29894
|
"venue"
|
|
29540
29895
|
];
|
|
29541
29896
|
RENDER_NONE = null;
|
|
@@ -29567,12 +29922,42 @@ var init_result = __esm({
|
|
|
29567
29922
|
preview: (r) => r.preview === null ? null : `preview ${r.preview.url}`,
|
|
29568
29923
|
containerImage: (r) => r.containerImage === null ? null : `image ${r.containerImage}`,
|
|
29569
29924
|
containerImageDigest: (r) => r.containerImageDigest === null ? null : `image digest ${r.containerImageDigest}`,
|
|
29570
|
-
|
|
29925
|
+
// Shown only when a human chose the environment. `detected` is the ordinary case and
|
|
29926
|
+
// saying so on every run would train the reader to skip the line that matters.
|
|
29927
|
+
imageSource: (r) => r.imageSource === "detected" || r.imageSource === "none" ? null : `image source ${r.imageSource} (not signed)`,
|
|
29928
|
+
// Printed through `leakState` below, which knows WHY a false is false. Rendering both would
|
|
29929
|
+
// print the leak warning on a run where we merely could not look (TERM-1144).
|
|
29930
|
+
leaksClean: RENDER_NONE,
|
|
29931
|
+
// Silent when clean and when refused, as the boolean's line was. The two not-a-leak states
|
|
29932
|
+
// get their own sentence, because "we could not check" read as "we found a leak" is the
|
|
29933
|
+
// exact confusion this field exists to end.
|
|
29934
|
+
leakState: (r) => {
|
|
29935
|
+
switch (r.leakState) {
|
|
29936
|
+
case null:
|
|
29937
|
+
case "clean":
|
|
29938
|
+
return null;
|
|
29939
|
+
case "leak":
|
|
29940
|
+
return "WARNING labelled Docker objects survived teardown";
|
|
29941
|
+
case "inconclusive":
|
|
29942
|
+
return "leak check inconclusive \u2014 no labelled container was seen while the run was live, so finding nothing afterwards proves nothing";
|
|
29943
|
+
case "unobserved":
|
|
29944
|
+
return "leak check not taken \u2014 we could not check what was left after teardown";
|
|
29945
|
+
}
|
|
29946
|
+
},
|
|
29571
29947
|
// Absent on most runs, so it prints only when there is something to say. Silence
|
|
29572
29948
|
// here is the honest rendering of "no venue answered": a placeholder line would
|
|
29573
29949
|
// invite a reader to treat an unanswered probe as a described venue.
|
|
29574
29950
|
venue: (r) => r.venue === null ? null : renderVenueLine(r.venue)
|
|
29575
29951
|
};
|
|
29952
|
+
OUTCOME_EXIT_CODES = {
|
|
29953
|
+
completed: 0,
|
|
29954
|
+
"tests-failed": 1,
|
|
29955
|
+
"no-tests-observed": 1,
|
|
29956
|
+
"budget-exceeded": 1,
|
|
29957
|
+
"counts-unparsed": 2,
|
|
29958
|
+
"test-command-unavailable": 2,
|
|
29959
|
+
"environment-exhausted": 2
|
|
29960
|
+
};
|
|
29576
29961
|
}
|
|
29577
29962
|
});
|
|
29578
29963
|
|
|
@@ -29693,12 +30078,23 @@ function toAcceptancePredicate(pair, opts = {}) {
|
|
|
29693
30078
|
if (why !== null)
|
|
29694
30079
|
return refuse3("test-command-origin-unattested", `the ${side} run ${why}`);
|
|
29695
30080
|
}
|
|
29696
|
-
if (patched.testCommandSource === "developer-declared") {
|
|
29697
|
-
return refuse3("test-command-origin-unattested", "the developer supplied the test command (unreachable \u2014 the source rules above cover it)
|
|
30081
|
+
if (patched.testCommandSource === "developer-declared" || patched.testCommandSource === "operator-declared") {
|
|
30082
|
+
return refuse3("test-command-origin-unattested", `${patched.testCommandSource === "developer-declared" ? "the developer" : "an operator"} supplied the test command (unreachable \u2014 the source rules above cover it)`);
|
|
29698
30083
|
}
|
|
29699
30084
|
if (baseline.testCommandSource !== patched.testCommandSource) {
|
|
29700
30085
|
return refuse3("test-command-origin-unattested", `the pair disagrees on where the command came from: baseline ${baseline.testCommandSource}, patched ${patched.testCommandSource}. One signed value cannot describe both.`);
|
|
29701
30086
|
}
|
|
30087
|
+
for (const [side, source, image] of [
|
|
30088
|
+
["patched", patched.imageSource, patched.containerImage],
|
|
30089
|
+
["baseline", baseline.imageSource, baseline.containerImage]
|
|
30090
|
+
]) {
|
|
30091
|
+
const why = IMAGE_SOURCE_IS_SIGNABLE[source](image);
|
|
30092
|
+
if (why !== null)
|
|
30093
|
+
return refuse3("image-origin-unattested", `the ${side} run ${why}`);
|
|
30094
|
+
}
|
|
30095
|
+
if (baseline.imageSource !== patched.imageSource) {
|
|
30096
|
+
return refuse3("image-origin-unattested", `the pair disagrees on where the image came from: baseline ${baseline.imageSource}, patched ${patched.imageSource}. The environment is part of what the statement says was held constant.`);
|
|
30097
|
+
}
|
|
29702
30098
|
if (baseline.containerImage !== patched.containerImage) {
|
|
29703
30099
|
return refuse3("pair-disagrees-on-image", `baseline ran in ${String(baseline.containerImage)} and patched in ${String(patched.containerImage)}. The signed measurement names one image, so a pair from two environments would attribute to the patch whatever the image changed.`);
|
|
29704
30100
|
}
|
|
@@ -29755,7 +30151,7 @@ function signRunStatement(predicate, privateKey, keyid) {
|
|
|
29755
30151
|
const statement = createAcceptanceStatement(predicate);
|
|
29756
30152
|
return { statement, envelope: signStatement(statement, privateKey, keyid) };
|
|
29757
30153
|
}
|
|
29758
|
-
var OUTCOME_TO_BUDGET, BASELINE_IS_A_VERDICT, CONTRADICTS_COUNTS, SOURCE_IS_SIGNABLE, ATTEST_REFUSAL_REASONS, refuse3, LOCAL_MEASUREMENT_PREFIX, REFERENCE_DOMAIN_COMPONENT, REFERENCE_DOMAIN_NAME, REFERENCE_IPV6, REFERENCE_DOMAIN, REFERENCE_PATH_COMPONENT, REPO_DIGEST_RE;
|
|
30154
|
+
var OUTCOME_TO_BUDGET, BASELINE_IS_A_VERDICT, CONTRADICTS_COUNTS, SOURCE_IS_SIGNABLE, IMAGE_SOURCE_IS_SIGNABLE, ATTEST_REFUSAL_REASONS, refuse3, LOCAL_MEASUREMENT_PREFIX, REFERENCE_DOMAIN_COMPONENT, REFERENCE_DOMAIN_NAME, REFERENCE_IPV6, REFERENCE_DOMAIN, REFERENCE_PATH_COMPONENT, REPO_DIGEST_RE;
|
|
29759
30155
|
var init_attestation2 = __esm({
|
|
29760
30156
|
"../../packages/envrun/dist/attestation.js"() {
|
|
29761
30157
|
"use strict";
|
|
@@ -29811,11 +30207,25 @@ var init_attestation2 = __esm({
|
|
|
29811
30207
|
// The party under verification chose it, and no signed member can say so. Per ADR-005
|
|
29812
30208
|
// Decision 2, emit nothing rather than pick the closest word.
|
|
29813
30209
|
"developer-declared": () => "had its test command supplied by the developer whose work is under verification, and the signed vocabulary has no member for that. `founder-declared` would attribute the choice to the other party; `detected` would claim the repo chose it. Both are false.",
|
|
30210
|
+
// US, out of band, per posting — the twin of `IMAGE_SOURCE_IS_SIGNABLE['operator-declared']`
|
|
30211
|
+
// and refusing for the same reason. `founder-declared` is the nearest signed member and it
|
|
30212
|
+
// is still false: the poster did not choose this, we did, and signing our own choice under
|
|
30213
|
+
// the counterparty's name is the specific false attribution the `developer-declared` entry
|
|
30214
|
+
// above exists to refuse. Decision 2 — emit nothing rather than pick the closest word.
|
|
30215
|
+
"operator-declared": () => "had its test command chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked command as one the repository chose for itself.",
|
|
29814
30216
|
// `none` means nobody chose a command, so a command beside it is a contradiction. Shadowed
|
|
29815
30217
|
// today — `thrun.ts` sets `none` only when the derived command is null, and `no-test-command`
|
|
29816
30218
|
// fires first — but that coupling runs through `runEnvironmentSpec` and lives in no type.
|
|
29817
30219
|
none: (command) => command === null ? null : `records its command source as \`none\` \u2014 nobody chose one \u2014 beside the command ${JSON.stringify(command)}`
|
|
29818
30220
|
};
|
|
30221
|
+
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
30222
|
+
detected: () => null,
|
|
30223
|
+
"operator-declared": () => "had its container image chosen by an operator out of band, and the signed vocabulary has no member for that. Signing it would present a hand-picked environment as the one the runtime mapping selected.",
|
|
30224
|
+
"developer-declared": () => "had its container image supplied by the developer whose work is under verification. A chosen interpreter turns a red suite green as surely as a chosen test command.",
|
|
30225
|
+
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
30226
|
+
// `SOURCE_IS_SIGNABLE.none` argument, applied to the other field.
|
|
30227
|
+
none: (image) => image === null ? null : `records its image source as \`none\` \u2014 nothing was booted \u2014 beside the image ${JSON.stringify(image)}`
|
|
30228
|
+
};
|
|
29819
30229
|
ATTEST_REFUSAL_REASONS = [
|
|
29820
30230
|
"our-environment-failed",
|
|
29821
30231
|
"run-was-refused",
|
|
@@ -29857,7 +30267,11 @@ var init_attestation2 = __esm({
|
|
|
29857
30267
|
// The signed triple must be reproducible from what it names — see the guard.
|
|
29858
30268
|
"patch-binding-incomplete",
|
|
29859
30269
|
"outcome-contradicts-counts",
|
|
29860
|
-
"test-command-origin-unattested"
|
|
30270
|
+
"test-command-origin-unattested",
|
|
30271
|
+
// The environment half of the pair above. `pair-disagrees-on-image` compares image NAMES;
|
|
30272
|
+
// this one asks who CHOSE the name, which no comparison of the two halves can reveal when
|
|
30273
|
+
// both were handed the same override.
|
|
30274
|
+
"image-origin-unattested"
|
|
29861
30275
|
];
|
|
29862
30276
|
refuse3 = (reason, detail) => ({
|
|
29863
30277
|
ok: false,
|
|
@@ -30361,13 +30775,20 @@ function gcpBootArgv(p) {
|
|
|
30361
30775
|
// steal". Attaching an account removes that, so the safety now rests on two things,
|
|
30362
30776
|
// and this change MUST land together with proof #2 — never ahead of it:
|
|
30363
30777
|
//
|
|
30364
|
-
// 1. `--no-scopes`
|
|
30365
|
-
// No scopes → the OAuth access-token endpoint serves nothing
|
|
30366
|
-
// TERM-706)
|
|
30367
|
-
//
|
|
30368
|
-
//
|
|
30369
|
-
//
|
|
30370
|
-
//
|
|
30778
|
+
// 1. `--no-scopes` and a NARROW grant set bound the BLAST RADIUS of a lifted
|
|
30779
|
+
// token. No scopes → the OAuth access-token endpoint serves nothing
|
|
30780
|
+
// (measured, TERM-706). This said "ZERO project roles" until 2026-09-18, and
|
|
30781
|
+
// that was never true of the account we ship: measured live, `venue-identity@`
|
|
30782
|
+
// holds `roles/confidentialcomputing.workloadUser` on the project and
|
|
30783
|
+
// `roles/artifactregistry.reader` on the `venue-images` repository alone —
|
|
30784
|
+
// the same two grants the Confidential Space note below already named, so this
|
|
30785
|
+
// file contradicted itself. Neither reaches a second repository, a bucket or
|
|
30786
|
+
// another VM, which is the property "zero roles" was reaching for. But the
|
|
30787
|
+
// token is NOT valueless: it is the attestation evidence itself, so a lifted
|
|
30788
|
+
// token still authorizes a false claim about WHERE a run happened (the
|
|
30789
|
+
// steal-a-true-token attack in the item-2 spike). `--no-scopes` stays because
|
|
30790
|
+
// it removes lateral GCP access; it does not make losing the identity token
|
|
30791
|
+
// cheap.
|
|
30371
30792
|
// 2. The untrusted code cannot reach the metadata server to lift the token at all.
|
|
30372
30793
|
// The test step runs `--network=none`; the install step runs on an `--internal`
|
|
30373
30794
|
// network whose only egress is a CONNECT-only, registry-allowlisted proxy that
|
|
@@ -31847,11 +32268,7 @@ function makeLease(p) {
|
|
|
31847
32268
|
}
|
|
31848
32269
|
try {
|
|
31849
32270
|
check("counting what the run left behind");
|
|
31850
|
-
return Promise.resolve(
|
|
31851
|
-
observed: true,
|
|
31852
|
-
census: census(p.docker, label),
|
|
31853
|
-
unobservedReason: null
|
|
31854
|
-
});
|
|
32271
|
+
return Promise.resolve(censusReport(p.docker, label));
|
|
31855
32272
|
} catch (err) {
|
|
31856
32273
|
return Promise.resolve({
|
|
31857
32274
|
observed: false,
|
|
@@ -32119,7 +32536,7 @@ function localDockerPlacement() {
|
|
|
32119
32536
|
kind: "local-docker",
|
|
32120
32537
|
refusal: null,
|
|
32121
32538
|
venue: () => localVenue(),
|
|
32122
|
-
imageFor: (runtime, override, version2) => imageForRuntime(runtime, override, version2)
|
|
32539
|
+
imageFor: (runtime, override, version2, variant) => imageForRuntime(runtime, override, version2, variant)
|
|
32123
32540
|
};
|
|
32124
32541
|
}
|
|
32125
32542
|
function hostedPoolPlacement() {
|
|
@@ -32127,7 +32544,7 @@ function hostedPoolPlacement() {
|
|
|
32127
32544
|
kind: "hosted-pool",
|
|
32128
32545
|
refusal: null,
|
|
32129
32546
|
venue: () => hostedVenue(),
|
|
32130
|
-
imageFor: (runtime, override, version2) => imageForRuntime(runtime, override, version2)
|
|
32547
|
+
imageFor: (runtime, override, version2, variant) => imageForRuntime(runtime, override, version2, variant)
|
|
32131
32548
|
};
|
|
32132
32549
|
}
|
|
32133
32550
|
function placementFor(kind) {
|
|
@@ -32692,6 +33109,9 @@ function detectRuntime(repo) {
|
|
|
32692
33109
|
if (repo.listNames("").some((name) => /\.(?:csproj|fsproj|sln)$/.test(name))) {
|
|
32693
33110
|
candidates.push("dotnet");
|
|
32694
33111
|
}
|
|
33112
|
+
if (candidates.length === 0 && repo.listFiles("").some((f) => f.endsWith(".java"))) {
|
|
33113
|
+
candidates.push("jvm");
|
|
33114
|
+
}
|
|
32695
33115
|
return { runtime: candidates[0] ?? "unknown", candidates };
|
|
32696
33116
|
}
|
|
32697
33117
|
function readJsonObject(repo, path5) {
|
|
@@ -32839,6 +33259,11 @@ function basePythonInstallCommand(repo) {
|
|
|
32839
33259
|
}
|
|
32840
33260
|
return null;
|
|
32841
33261
|
}
|
|
33262
|
+
function rehearse(command) {
|
|
33263
|
+
const copy = '"$R/.terminalhire-rehearsal"';
|
|
33264
|
+
const home = '"$R/.terminalhire-rehearsal-home"';
|
|
33265
|
+
return `{ R="$HOME"; rm -rf ${copy} ${home}; mkdir -p ${home} && cp -R . ${copy} && (cd ${copy} && HOME=${home} GRADLE_USER_HOME="$R/.gradle" JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -Duser.home=$R/.terminalhire-rehearsal-home" ${command}); rm -rf ${copy} ${home}; true; }`;
|
|
33266
|
+
}
|
|
32842
33267
|
function otherRuntimeCommands(repo, runtime) {
|
|
32843
33268
|
switch (runtime) {
|
|
32844
33269
|
case "go":
|
|
@@ -32866,10 +33291,21 @@ function otherRuntimeCommands(repo, runtime) {
|
|
|
32866
33291
|
case "dotnet":
|
|
32867
33292
|
return { install: "dotnet restore", test: "dotnet test" };
|
|
32868
33293
|
case "jvm": {
|
|
32869
|
-
if (repo.exists(
|
|
32870
|
-
return { install:
|
|
33294
|
+
if (!JVM_BUILD_FILES.some((file) => repo.exists(file)))
|
|
33295
|
+
return { install: null, test: null };
|
|
33296
|
+
if (repo.exists("pom.xml")) {
|
|
33297
|
+
return {
|
|
33298
|
+
install: `mvn -B dependency:go-offline && ${rehearse('mvn -B test -Dmaven.test.failure.ignore=true -Dmaven.repo.local="$R/.m2/repository"')}`,
|
|
33299
|
+
test: "mvn -B -o test"
|
|
33300
|
+
};
|
|
33301
|
+
}
|
|
32871
33302
|
const wrapper = repo.exists("gradlew") ? "./gradlew" : "gradle";
|
|
32872
|
-
return {
|
|
33303
|
+
return {
|
|
33304
|
+
install: `${wrapper} dependencies && ${rehearse(`${wrapper} test --continue`)}`,
|
|
33305
|
+
// `--no-build-cache`: the rehearsal above can fill Gradle's build cache, and a
|
|
33306
|
+
// test task restored FROM-CACHE runs nothing and prints no count.
|
|
33307
|
+
test: `${wrapper} test --offline --no-build-cache`
|
|
33308
|
+
};
|
|
32873
33309
|
}
|
|
32874
33310
|
default:
|
|
32875
33311
|
return { install: null, test: null };
|
|
@@ -32901,6 +33337,15 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
32901
33337
|
push(".ruby-version", repo.readText(".ruby-version"));
|
|
32902
33338
|
} else if (runtime === "dotnet") {
|
|
32903
33339
|
push("global.json sdk.version", readStringField(readObjectField(readJsonObject(repo, "global.json"), "sdk"), "version"));
|
|
33340
|
+
} else if (runtime === "jvm") {
|
|
33341
|
+
const pom = repo.readText("pom.xml");
|
|
33342
|
+
const gradle = repo.readText("build.gradle") ?? repo.readText("build.gradle.kts");
|
|
33343
|
+
push("build.gradle toolchain languageVersion", javaMajor(matchFirst(gradle, /JavaLanguageVersion\.of\(\s*["']?(\d+)["']?\s*\)/) ?? matchFirst(gradle, /jvmToolchain\(\s*(\d+)\s*\)/)));
|
|
33344
|
+
push(".java-version", javaMajor(repo.readText(".java-version")));
|
|
33345
|
+
push("pom.xml maven.compiler.release", javaMajor(matchFirst(pom, /<maven\.compiler\.release>\s*([^<\s]+)\s*</)));
|
|
33346
|
+
push("pom.xml java.version", javaMajor(matchFirst(pom, /<java\.version>\s*([^<\s]+)\s*</)));
|
|
33347
|
+
push("pom.xml maven.compiler.source", javaMajor(matchFirst(pom, /<maven\.compiler\.source>\s*([^<\s]+)\s*</)));
|
|
33348
|
+
push("build.gradle sourceCompatibility", javaMajor(matchFirst(gradle, /sourceCompatibility\s*=\s*JavaVersion\.VERSION_([\d_]+)/)?.replace("_", ".") ?? matchFirst(gradle, /sourceCompatibility\s*=\s*["']?([\d.]+)["']?/)));
|
|
32904
33349
|
}
|
|
32905
33350
|
let rangeFound = null;
|
|
32906
33351
|
for (const source of sources) {
|
|
@@ -32914,13 +33359,21 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
32914
33359
|
}
|
|
32915
33360
|
return { version: null, searched: sources.map((s) => s.label), rangeFound };
|
|
32916
33361
|
}
|
|
33362
|
+
function javaMajor(text) {
|
|
33363
|
+
if (text === null)
|
|
33364
|
+
return null;
|
|
33365
|
+
const match2 = /^(?:1\.(\d+)|(\d+))(?:[._][\d_.]*)?$/.exec(text.trim());
|
|
33366
|
+
if (match2 === null)
|
|
33367
|
+
return null;
|
|
33368
|
+
return match2[1] ?? match2[2] ?? null;
|
|
33369
|
+
}
|
|
32917
33370
|
function matchFirst(text, pattern) {
|
|
32918
33371
|
if (text === null)
|
|
32919
33372
|
return null;
|
|
32920
33373
|
const match2 = pattern.exec(text);
|
|
32921
33374
|
return match2 === null ? null : match2[1];
|
|
32922
33375
|
}
|
|
32923
|
-
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
33376
|
+
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, JVM_BUILD_FILES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
32924
33377
|
var init_manifest2 = __esm({
|
|
32925
33378
|
"../../packages/envspec/dist/manifest.js"() {
|
|
32926
33379
|
"use strict";
|
|
@@ -32934,6 +33387,7 @@ var init_manifest2 = __esm({
|
|
|
32934
33387
|
{ runtime: "dotnet", files: [] }
|
|
32935
33388
|
];
|
|
32936
33389
|
MANIFEST_FILENAMES = RUNTIME_MANIFESTS.flatMap((m) => m.files).concat(["*.csproj", "*.fsproj", "*.sln"]).sort();
|
|
33390
|
+
JVM_BUILD_FILES = ["build.gradle", "build.gradle.kts", "pom.xml"];
|
|
32937
33391
|
NPM_PLACEHOLDER_TEST = /^echo\s+["']?Error:\s*no test specified["']?\s*&&\s*exit\s+1$/;
|
|
32938
33392
|
REQUIREMENT_SPECIFIER = /^[A-Za-z0-9._-]+(\[[A-Za-z0-9._,-]+\])?([<>=!~]=?[A-Za-z0-9._*+-]+(,[<>=!~]=?[A-Za-z0-9._*+-]+)*)?$/;
|
|
32939
33393
|
EXACT_VERSION = /^v?(\d+(?:\.\d+){0,2})$/;
|
|
@@ -33330,7 +33784,7 @@ function deriveFromReader(repo) {
|
|
|
33330
33784
|
searched: MANIFEST_FILENAMES,
|
|
33331
33785
|
detail: `no ecosystem manifest was found at the repo root (looked for ${MANIFEST_FILENAMES.join(", ")}), so the language runtime could not be identified`
|
|
33332
33786
|
});
|
|
33333
|
-
} else {
|
|
33787
|
+
} else if (runtime !== "jvm" || JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
33334
33788
|
derivedFrom.add("manifest");
|
|
33335
33789
|
}
|
|
33336
33790
|
if (detection.candidates.length > 1) {
|
|
@@ -33494,12 +33948,13 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
33494
33948
|
const setup = SETUP_ACTIONS[runtime];
|
|
33495
33949
|
const searched = [];
|
|
33496
33950
|
let rangeFound = null;
|
|
33951
|
+
const pin = (raw) => runtime === "jvm" ? javaMajor(raw) : exactVersion(raw);
|
|
33497
33952
|
if (job !== null && setup !== void 0) {
|
|
33498
33953
|
const direct = findActionInput(job, setup.action, setup.input);
|
|
33499
33954
|
if (direct !== null) {
|
|
33500
33955
|
searched.push(`${job.file} ${setup.action} ${setup.input}`);
|
|
33501
33956
|
const reduced = reduceExpression(direct.command, job.singletons);
|
|
33502
|
-
const exact =
|
|
33957
|
+
const exact = pin(reduced);
|
|
33503
33958
|
if (exact !== null)
|
|
33504
33959
|
return { value: exact, searched, rangeFound: null };
|
|
33505
33960
|
if (reduced !== null)
|
|
@@ -33508,7 +33963,7 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
33508
33963
|
const viaFile = findActionInput(job, setup.action, setup.fileInput);
|
|
33509
33964
|
if (viaFile !== null) {
|
|
33510
33965
|
searched.push(`${job.file} ${setup.action} ${setup.fileInput} -> ${viaFile.command}`);
|
|
33511
|
-
const exact =
|
|
33966
|
+
const exact = pin(repo.readText(viaFile.command));
|
|
33512
33967
|
if (exact !== null)
|
|
33513
33968
|
return { value: exact, searched, rangeFound: null };
|
|
33514
33969
|
}
|
|
@@ -33533,6 +33988,8 @@ function testSearchPaths(runtime, workflowFiles) {
|
|
|
33533
33988
|
paths.push("**/*_test.go");
|
|
33534
33989
|
if (runtime === "ruby")
|
|
33535
33990
|
paths.push("Gemfile", "Rakefile");
|
|
33991
|
+
if (runtime === "jvm")
|
|
33992
|
+
paths.push(...JVM_BUILD_FILES);
|
|
33536
33993
|
if (runtime === "unknown")
|
|
33537
33994
|
paths.push(...MANIFEST_FILENAMES);
|
|
33538
33995
|
return [...new Set(paths)].sort();
|
|
@@ -33550,6 +34007,9 @@ function describeTestSearch(repo, runtime, workflowFiles) {
|
|
|
33550
34007
|
if (runtime === "python") {
|
|
33551
34008
|
return `${ciPart}, and nothing in the repo names a test runner \u2014 no \`[tool.pytest.ini_options]\`, no \`pytest.ini\`, and no pytest dependency in \`pyproject.toml\` or a requirements file`;
|
|
33552
34009
|
}
|
|
34010
|
+
if (runtime === "jvm" && !JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
34011
|
+
return `${ciPart}, and the repo has Java sources but no build file (${JVM_BUILD_FILES.join(", ")}), so there is no build to run tests with. Compiling the sources with \`javac\` alone would run no tests`;
|
|
34012
|
+
}
|
|
33553
34013
|
return `${ciPart}, and no ${runtime} test convention applies to this tree`;
|
|
33554
34014
|
}
|
|
33555
34015
|
function installSearchPaths(runtime, workflowFiles) {
|
|
@@ -33558,6 +34018,8 @@ function installSearchPaths(runtime, workflowFiles) {
|
|
|
33558
34018
|
paths.push("package-lock.json", "pnpm-lock.yaml", "yarn.lock");
|
|
33559
34019
|
if (runtime === "python")
|
|
33560
34020
|
paths.push("poetry.lock", "pyproject.toml", "requirements.txt", "uv.lock");
|
|
34021
|
+
if (runtime === "jvm")
|
|
34022
|
+
paths.push(...JVM_BUILD_FILES);
|
|
33561
34023
|
if (runtime === "unknown")
|
|
33562
34024
|
paths.push(...MANIFEST_FILENAMES);
|
|
33563
34025
|
return [...new Set(paths)].sort();
|
|
@@ -33636,12 +34098,41 @@ var init_dist3 = __esm({
|
|
|
33636
34098
|
}
|
|
33637
34099
|
});
|
|
33638
34100
|
|
|
34101
|
+
// ../../packages/envrun/dist/gradleTestSummary.js
|
|
34102
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync16 } from "fs";
|
|
34103
|
+
import { join as join28 } from "path";
|
|
34104
|
+
function stageGradleTestSummary(jailHome) {
|
|
34105
|
+
const dir = join28(jailHome, ".gradle", "init.d");
|
|
34106
|
+
mkdirSync5(dir, { recursive: true });
|
|
34107
|
+
writeFileSync16(join28(dir, "terminalhire-test-summary.gradle"), GRADLE_TEST_SUMMARY_INIT);
|
|
34108
|
+
}
|
|
34109
|
+
var GRADLE_TEST_MARKER, GRADLE_TEST_SUMMARY_INIT;
|
|
34110
|
+
var init_gradleTestSummary = __esm({
|
|
34111
|
+
"../../packages/envrun/dist/gradleTestSummary.js"() {
|
|
34112
|
+
"use strict";
|
|
34113
|
+
GRADLE_TEST_MARKER = "terminalhire-gradle-tests:";
|
|
34114
|
+
GRADLE_TEST_SUMMARY_INIT = `// Written by terminalhire (TERM-1122): prints each Test task's counts, because
|
|
34115
|
+
// Gradle prints none when every test passes.
|
|
34116
|
+
allprojects {
|
|
34117
|
+
tasks.withType(Test).configureEach { task ->
|
|
34118
|
+
def label = task.path
|
|
34119
|
+
task.afterSuite { desc, result ->
|
|
34120
|
+
if (desc.parent == null) {
|
|
34121
|
+
println "${GRADLE_TEST_MARKER} task=\${label} total=\${result.testCount} passed=\${result.successfulTestCount} failed=\${result.failedTestCount} skipped=\${result.skippedTestCount}"
|
|
34122
|
+
}
|
|
34123
|
+
}
|
|
34124
|
+
}
|
|
34125
|
+
}
|
|
34126
|
+
`;
|
|
34127
|
+
}
|
|
34128
|
+
});
|
|
34129
|
+
|
|
33639
34130
|
// ../../packages/envrun/dist/thrun.js
|
|
33640
34131
|
import { execFileSync, spawnSync as spawnSync6 } from "child_process";
|
|
33641
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
34132
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync4, rmSync as rmSync9 } from "fs";
|
|
33642
34133
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
33643
34134
|
import { tmpdir as tmpdir4 } from "os";
|
|
33644
|
-
import { join as
|
|
34135
|
+
import { join as join29 } from "path";
|
|
33645
34136
|
function git(repoDir, args, allowNonZero = false) {
|
|
33646
34137
|
const res = spawnSync6("git", [...args], {
|
|
33647
34138
|
cwd: repoDir,
|
|
@@ -33656,7 +34147,7 @@ function git(repoDir, args, allowNonZero = false) {
|
|
|
33656
34147
|
return res.stdout ?? "";
|
|
33657
34148
|
}
|
|
33658
34149
|
function collectWorkingDiff(repoDir, opts = {}) {
|
|
33659
|
-
if (!existsSync12(
|
|
34150
|
+
if (!existsSync12(join29(repoDir, ".git"))) {
|
|
33660
34151
|
throw new ThRunError(`${repoDir} is not a git checkout (no .git). \`th run\` ships the working diff, so it needs a repository to read one from.`);
|
|
33661
34152
|
}
|
|
33662
34153
|
const headSha = git(repoDir, ["rev-parse", "HEAD"]).trim();
|
|
@@ -33804,7 +34295,7 @@ function credentialFreeHome() {
|
|
|
33804
34295
|
return credentialFreeHomeDir;
|
|
33805
34296
|
let made;
|
|
33806
34297
|
try {
|
|
33807
|
-
made = mkdtempSync4(
|
|
34298
|
+
made = mkdtempSync4(join29(tmpdir4(), "th-run-nohome-"));
|
|
33808
34299
|
} catch (err) {
|
|
33809
34300
|
throw new RunRefusalError("could not create the empty directory this clone uses as its home, so the clone would read the credentials on this machine instead. That is our environment failing, not your tests: check that the temp directory is writable.", { cause: err });
|
|
33810
34301
|
}
|
|
@@ -33879,7 +34370,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
33879
34370
|
if (persisted !== null) {
|
|
33880
34371
|
throw new RunRefusalError(`refusing to clone from a URL carrying ${persisted}: \`git remote add\` writes the source verbatim into .git/config, which is mounted where the repo\u2019s own test command runs. Fetch with the credential out of band so it is never written to disk \u2014 this runner takes one as an HTTP header, which is never persisted.`);
|
|
33881
34372
|
}
|
|
33882
|
-
|
|
34373
|
+
mkdirSync6(opts.dest, { recursive: true });
|
|
33883
34374
|
const runOut = (args) => execFileSync("git", [...gitConfigArgs(), ...args], {
|
|
33884
34375
|
cwd: opts.dest,
|
|
33885
34376
|
encoding: "utf8",
|
|
@@ -33918,7 +34409,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
33918
34409
|
}
|
|
33919
34410
|
function scrubCloneSource(dest, run3) {
|
|
33920
34411
|
run3(["remote", "remove", "origin"]);
|
|
33921
|
-
rmSync9(
|
|
34412
|
+
rmSync9(join29(dest, ".git", "FETCH_HEAD"), { force: true });
|
|
33922
34413
|
}
|
|
33923
34414
|
function publishableTarget(url) {
|
|
33924
34415
|
if (separatorInTarget(url) !== null)
|
|
@@ -34057,12 +34548,18 @@ function refusedRun(fields) {
|
|
|
34057
34548
|
treeDigest: null,
|
|
34058
34549
|
baselinePatchSha256: null,
|
|
34059
34550
|
testCommandSource: "none",
|
|
34551
|
+
// Nothing was booted, so nobody chose an image. Same reasoning as `containerImage: null`
|
|
34552
|
+
// below: it must not read as an image we picked and cannot name.
|
|
34553
|
+
imageSource: "none",
|
|
34060
34554
|
boundaryRefusals: fields.boundaryRefusals,
|
|
34061
34555
|
touchedPaths: fields.touchedPaths,
|
|
34062
34556
|
preview: null,
|
|
34063
34557
|
containerImage: null,
|
|
34064
34558
|
containerImageDigest: null,
|
|
34065
34559
|
leaksClean: null,
|
|
34560
|
+
// Null for the same reason, and never `unobserved`: that word says we tried to take a
|
|
34561
|
+
// census and could not, and here there was nothing to take one of (TERM-1144).
|
|
34562
|
+
leakState: null,
|
|
34066
34563
|
// A refused run never held a lease, so there is no venue to describe. Same
|
|
34067
34564
|
// reasoning as `leaksClean` above: null because nothing happened, and it must
|
|
34068
34565
|
// not read as a venue we looked at and could not name.
|
|
@@ -34290,10 +34787,10 @@ async function runVerification(req, ctx) {
|
|
|
34290
34787
|
venueIdentity: null
|
|
34291
34788
|
};
|
|
34292
34789
|
}
|
|
34293
|
-
const stage =
|
|
34294
|
-
const cloneDir =
|
|
34295
|
-
const scratch =
|
|
34296
|
-
|
|
34790
|
+
const stage = join29(req.scratchRoot, runId);
|
|
34791
|
+
const cloneDir = join29(stage, "clone");
|
|
34792
|
+
const scratch = join29(stage, "scratch");
|
|
34793
|
+
mkdirSync6(scratch, { recursive: true });
|
|
34297
34794
|
assertSafeTargetSha(req.targetSha);
|
|
34298
34795
|
progress("clone", `${publishableTarget(req.targetRepo)} @ ${req.targetSha.slice(0, 12)}`);
|
|
34299
34796
|
cloneTargetAt({
|
|
@@ -34320,7 +34817,8 @@ async function runVerification(req, ctx) {
|
|
|
34320
34817
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
34321
34818
|
const spec = req.testCommandOverride === void 0 ? derived : { ...derived, testCommand: req.testCommandOverride };
|
|
34322
34819
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
34323
|
-
|
|
34820
|
+
refuseUnbuildableSpec(spec);
|
|
34821
|
+
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
34324
34822
|
const resolved = await resolveLease(placement, runId);
|
|
34325
34823
|
if (!resolved.ok) {
|
|
34326
34824
|
return {
|
|
@@ -34355,10 +34853,12 @@ async function runVerification(req, ctx) {
|
|
|
34355
34853
|
const lease = resolved.lease;
|
|
34356
34854
|
try {
|
|
34357
34855
|
buildJail(scratch);
|
|
34856
|
+
if (spec.runtime === "jvm")
|
|
34857
|
+
stageGradleTestSummary(localJailPaths(scratch).jail);
|
|
34358
34858
|
const venuePaths = await lease.stage({
|
|
34359
34859
|
cloneDir,
|
|
34360
34860
|
scratchRoot: scratch,
|
|
34361
|
-
previewDir:
|
|
34861
|
+
previewDir: join29(stage, "preview"),
|
|
34362
34862
|
// On a dispatched run the commit is the statement of what was tested, so
|
|
34363
34863
|
// it rides with the tree and the venue seam refuses a tree that is not
|
|
34364
34864
|
// that commit (design §6 item 4, TERM-892 — the guard lives in
|
|
@@ -34405,7 +34905,7 @@ async function runVerification(req, ctx) {
|
|
|
34405
34905
|
// that `founder-declared` (as this did for one review round) signs the counterparty's
|
|
34406
34906
|
// name onto the developer's choice, which is worse than laundering it as `detected`:
|
|
34407
34907
|
// it is a specific false attribution inside a field a reviewer trusts.
|
|
34408
|
-
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
34908
|
+
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : req.testCommandOverrideOrigin === "operator" ? "operator-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
34409
34909
|
boundaryRefusals: [],
|
|
34410
34910
|
touchedPaths: pre.touchedPaths,
|
|
34411
34911
|
preview: null,
|
|
@@ -34415,7 +34915,14 @@ async function runVerification(req, ctx) {
|
|
|
34415
34915
|
// that measures one; a run without it is recordable but not attestable —
|
|
34416
34916
|
// `toAcceptancePredicate` refuses `missing-image-digest` (TERM-893).
|
|
34417
34917
|
containerImageDigest: null,
|
|
34918
|
+
// The image half of the provenance pair above. `detected` means the runtime mapping
|
|
34919
|
+
// chose the environment; an override names the human. Defaulting an unstated origin to
|
|
34920
|
+
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
34921
|
+
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
34922
|
+
// the operator would sign our name onto their choice.
|
|
34923
|
+
imageSource: req.image === void 0 ? "detected" : req.imageOrigin === "operator" ? "operator-declared" : "developer-declared",
|
|
34418
34924
|
leaksClean: verdict.leaks.clean,
|
|
34925
|
+
leakState: verdict.leaks.state,
|
|
34419
34926
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
34420
34927
|
// `req.placement`, which is a request. `venueDescriptor.ts` carries the
|
|
34421
34928
|
// reasoning and the #735 failure that makes the distinction load-bearing.
|
|
@@ -34473,6 +34980,7 @@ var init_thrun = __esm({
|
|
|
34473
34980
|
init_execute();
|
|
34474
34981
|
init_placement();
|
|
34475
34982
|
init_venue();
|
|
34983
|
+
init_gradleTestSummary();
|
|
34476
34984
|
init_venueDescriptor();
|
|
34477
34985
|
init_result();
|
|
34478
34986
|
ThRunError = class extends Error {
|
|
@@ -34716,7 +35224,7 @@ var init_dbplan = __esm({
|
|
|
34716
35224
|
// ../../packages/envrun/dist/dbstack.js
|
|
34717
35225
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
34718
35226
|
import { randomBytes as randomBytes11 } from "crypto";
|
|
34719
|
-
import { mkdirSync as
|
|
35227
|
+
import { mkdirSync as mkdirSync7 } from "fs";
|
|
34720
35228
|
function installCommandFor(runner) {
|
|
34721
35229
|
switch (runner) {
|
|
34722
35230
|
case "sql":
|
|
@@ -34947,7 +35455,7 @@ function startDatabase(req) {
|
|
|
34947
35455
|
if (!ready.ok) {
|
|
34948
35456
|
throw new DbStackError(`INFRASTRUCTURE/INCONCLUSIVE: Postgres never accepted queries at 127.0.0.1:${String(creds.port)} within the readiness window: ${ready.detail}`);
|
|
34949
35457
|
}
|
|
34950
|
-
const
|
|
35458
|
+
const query2 = (sql) => {
|
|
34951
35459
|
const res = docker2([
|
|
34952
35460
|
"exec",
|
|
34953
35461
|
`--env=PGPASSWORD=${creds.password}`,
|
|
@@ -34995,7 +35503,7 @@ function startDatabase(req) {
|
|
|
34995
35503
|
credentials: creds,
|
|
34996
35504
|
image,
|
|
34997
35505
|
readyMs: ready.ms,
|
|
34998
|
-
query,
|
|
35506
|
+
query: query2,
|
|
34999
35507
|
runOnNetwork,
|
|
35000
35508
|
teardown
|
|
35001
35509
|
};
|
|
@@ -35058,8 +35566,8 @@ async function installLocalMigrationTooling(opts) {
|
|
|
35058
35566
|
};
|
|
35059
35567
|
}
|
|
35060
35568
|
const { jail, tmp } = buildJail(opts.scratchRoot);
|
|
35061
|
-
|
|
35062
|
-
|
|
35569
|
+
mkdirSync7(jail, { recursive: true });
|
|
35570
|
+
mkdirSync7(tmp, { recursive: true });
|
|
35063
35571
|
const spec = {
|
|
35064
35572
|
profile: "install",
|
|
35065
35573
|
clone: opts.repoDir,
|
|
@@ -35354,6 +35862,7 @@ __export(dist_exports, {
|
|
|
35354
35862
|
GOOGLE_JWKS_URL: () => GOOGLE_JWKS_URL,
|
|
35355
35863
|
HostedVenueError: () => HostedVenueError,
|
|
35356
35864
|
JWKS_FETCH_TIMEOUT_MS: () => JWKS_FETCH_TIMEOUT_MS,
|
|
35865
|
+
LEAK_STATES: () => LEAK_STATES,
|
|
35357
35866
|
LOCAL_MEASUREMENT_PREFIX: () => LOCAL_MEASUREMENT_PREFIX,
|
|
35358
35867
|
LabelWatch: () => LabelWatch,
|
|
35359
35868
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
@@ -35370,6 +35879,7 @@ __export(dist_exports, {
|
|
|
35370
35879
|
REDACTED_TARGET_SHA: () => REDACTED_TARGET_SHA,
|
|
35371
35880
|
RELEASED_LEASE_CENSUS_REASON: () => RELEASED_LEASE_CENSUS_REASON,
|
|
35372
35881
|
REPO_DIGEST_RE: () => REPO_DIGEST_RE,
|
|
35882
|
+
RUN_IMAGE_SOURCES: () => RUN_IMAGE_SOURCES,
|
|
35373
35883
|
RUN_LABEL_KEY: () => RUN_LABEL_KEY,
|
|
35374
35884
|
RUN_RESULT_FIELDS: () => RUN_RESULT_FIELDS,
|
|
35375
35885
|
RUN_RESULT_SCHEMA: () => RUN_RESULT_SCHEMA,
|
|
@@ -35386,6 +35896,7 @@ __export(dist_exports, {
|
|
|
35386
35896
|
VENUE_GCLOUD_CONFIG: () => VENUE_GCLOUD_CONFIG,
|
|
35387
35897
|
VENUE_SSH_USER: () => VENUE_SSH_USER,
|
|
35388
35898
|
VENV_DIR: () => VENV_DIR,
|
|
35899
|
+
VERIFICATION_OUTCOMES: () => VERIFICATION_OUTCOMES,
|
|
35389
35900
|
VenueRollbackError: () => VenueRollbackError,
|
|
35390
35901
|
acquireTransactionally: () => acquireTransactionally,
|
|
35391
35902
|
alembicChainPosition: () => alembicChainPosition,
|
|
@@ -35399,6 +35910,7 @@ __export(dist_exports, {
|
|
|
35399
35910
|
assertVenueOwnerDeclared: () => assertVenueOwnerDeclared,
|
|
35400
35911
|
bookkeepingFor: () => bookkeepingFor,
|
|
35401
35912
|
census: () => census,
|
|
35913
|
+
censusReport: () => censusReport,
|
|
35402
35914
|
censusTotal: () => censusTotal,
|
|
35403
35915
|
classifyBootFailure: () => classifyBootFailure,
|
|
35404
35916
|
classifyProbeFailure: () => classifyProbeFailure,
|
|
@@ -35418,6 +35930,7 @@ __export(dist_exports, {
|
|
|
35418
35930
|
detectRunner: () => detectRunner,
|
|
35419
35931
|
endOfOptionsUnsupported: () => endOfOptionsUnsupported,
|
|
35420
35932
|
ensureVenueServiceCredentials: () => ensureVenueServiceCredentials,
|
|
35933
|
+
exitCodeFor: () => exitCodeFor,
|
|
35421
35934
|
failureSourceOf: () => failureSourceOf,
|
|
35422
35935
|
findRunRefusal: () => findRunRefusal,
|
|
35423
35936
|
gcpBootArgv: () => gcpBootArgv,
|
|
@@ -35432,6 +35945,7 @@ __export(dist_exports, {
|
|
|
35432
35945
|
identityProbeCommand: () => identityProbeCommand,
|
|
35433
35946
|
imageForRuntime: () => imageForRuntime,
|
|
35434
35947
|
imageRepo: () => imageRepo,
|
|
35948
|
+
imageVariantFor: () => imageVariantFor,
|
|
35435
35949
|
installCommandFor: () => installCommandFor,
|
|
35436
35950
|
installLocalMigrationTooling: () => installLocalMigrationTooling,
|
|
35437
35951
|
isBookkeepingTable: () => isBookkeepingTable,
|
|
@@ -35461,6 +35975,7 @@ __export(dist_exports, {
|
|
|
35461
35975
|
readSchema: () => readSchema,
|
|
35462
35976
|
recordedApplied: () => recordedApplied,
|
|
35463
35977
|
refuseSshTransport: () => refuseSshTransport,
|
|
35978
|
+
refuseUnbuildableSpec: () => refuseUnbuildableSpec,
|
|
35464
35979
|
renderRunReport: () => renderRunReport,
|
|
35465
35980
|
renderVenueLine: () => renderVenueLine,
|
|
35466
35981
|
renderVerdictLine: () => renderVerdictLine,
|
|
@@ -35842,8 +36357,8 @@ __export(jpi_claim_exports, {
|
|
|
35842
36357
|
});
|
|
35843
36358
|
import {
|
|
35844
36359
|
readFileSync as readFileSync15,
|
|
35845
|
-
writeFileSync as
|
|
35846
|
-
mkdirSync as
|
|
36360
|
+
writeFileSync as writeFileSync17,
|
|
36361
|
+
mkdirSync as mkdirSync8,
|
|
35847
36362
|
mkdtempSync as mkdtempSync5,
|
|
35848
36363
|
renameSync as renameSync7,
|
|
35849
36364
|
existsSync as existsSync13,
|
|
@@ -35852,7 +36367,7 @@ import {
|
|
|
35852
36367
|
rmSync as rmSync10,
|
|
35853
36368
|
readdirSync as readdirSync3
|
|
35854
36369
|
} from "fs";
|
|
35855
|
-
import { join as
|
|
36370
|
+
import { join as join30, dirname as dirname9, isAbsolute as isAbsolute4, resolve as pathResolve } from "path";
|
|
35856
36371
|
import { createHash as createHash10 } from "crypto";
|
|
35857
36372
|
import { homedir as homedir15, hostname as osHostname } from "os";
|
|
35858
36373
|
import { execFile as execFile3, execFileSync as execFileSync2, spawnSync as spawnSync8 } from "child_process";
|
|
@@ -35871,7 +36386,7 @@ function markClaimNudged(id) {
|
|
|
35871
36386
|
const ids2 = readNudgedClaimIds();
|
|
35872
36387
|
ids2.add(id);
|
|
35873
36388
|
ensureStateDir(TERMINALHIRE_DIR11);
|
|
35874
|
-
|
|
36389
|
+
writeFileSync17(REPO_CONTINUITY_NUDGE_MARKER, JSON.stringify({ claimIds: [...ids2] }), "utf8");
|
|
35875
36390
|
} catch {
|
|
35876
36391
|
}
|
|
35877
36392
|
}
|
|
@@ -38136,7 +38651,7 @@ async function cmdAttach(id, worktree, branch) {
|
|
|
38136
38651
|
function workDirFor(repoFullName, issueNumber) {
|
|
38137
38652
|
const [owner, repo] = String(repoFullName).split("/");
|
|
38138
38653
|
const suffix = issueNumber ? `-${issueNumber}` : "";
|
|
38139
|
-
return
|
|
38654
|
+
return join30(homedir15(), "terminalhire", "work", `${owner}-${repo}${suffix}`);
|
|
38140
38655
|
}
|
|
38141
38656
|
function startBranchFor(repoFullName, issueNumber) {
|
|
38142
38657
|
const repo = String(repoFullName).split("/")[1] || "claim";
|
|
@@ -38392,7 +38907,7 @@ terminalhire claim: not started \u2014 starting forks ${claim.repoFullName} to y
|
|
|
38392
38907
|
);
|
|
38393
38908
|
process.exit(1);
|
|
38394
38909
|
}
|
|
38395
|
-
|
|
38910
|
+
mkdirSync8(join30(homedir15(), "terminalhire", "work"), { recursive: true });
|
|
38396
38911
|
const { createProgress: createProgress2, parseGitProgress: parseGitProgress2, splitProgressChunk: splitProgressChunk2, shStream: shStream2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
38397
38912
|
const progress = createProgress2();
|
|
38398
38913
|
let forkFullName;
|
|
@@ -38518,7 +39033,7 @@ function founderPostingIdOf(claim) {
|
|
|
38518
39033
|
}
|
|
38519
39034
|
function sliceWorkDirFor(claimLocalId) {
|
|
38520
39035
|
const safe = String(claimLocalId).replace(/[^A-Za-z0-9._-]/g, "-");
|
|
38521
|
-
return
|
|
39036
|
+
return join30(homedir15(), "terminalhire", "work", `slice-${safe}`);
|
|
38522
39037
|
}
|
|
38523
39038
|
function assertNoBooleanPath(dest, flagName) {
|
|
38524
39039
|
const last = String(dest).split(/[\\/]/).filter(Boolean).pop();
|
|
@@ -38635,9 +39150,9 @@ function writeSliceFiles(destDir, files) {
|
|
|
38635
39150
|
const unavailable = [];
|
|
38636
39151
|
for (const f of files) {
|
|
38637
39152
|
if (typeof f.content === "string") {
|
|
38638
|
-
const abs =
|
|
38639
|
-
|
|
38640
|
-
|
|
39153
|
+
const abs = join30(destDir, f.path);
|
|
39154
|
+
mkdirSync8(dirname9(abs), { recursive: true });
|
|
39155
|
+
writeFileSync17(abs, f.content, "utf8");
|
|
38641
39156
|
written.push(f.path);
|
|
38642
39157
|
} else {
|
|
38643
39158
|
unavailable.push({ path: f.path, reason: f.unavailableReason || "(no reason given)" });
|
|
@@ -38666,7 +39181,7 @@ function writeDeliveredBrief(destDir, spec) {
|
|
|
38666
39181
|
function ensureExcludedPackDir(destDir) {
|
|
38667
39182
|
let occupant = null;
|
|
38668
39183
|
try {
|
|
38669
|
-
occupant = lstatSync3(
|
|
39184
|
+
occupant = lstatSync3(join30(destDir, BRIEF_DIR));
|
|
38670
39185
|
} catch (err) {
|
|
38671
39186
|
if (err?.code !== "ENOENT") {
|
|
38672
39187
|
return {
|
|
@@ -38681,12 +39196,12 @@ function ensureExcludedPackDir(destDir) {
|
|
|
38681
39196
|
reason: `${BRIEF_DIR}/ already exists in the delivered tree, and excluding it would hide that content from your patch`
|
|
38682
39197
|
};
|
|
38683
39198
|
}
|
|
38684
|
-
const excludeFile =
|
|
39199
|
+
const excludeFile = join30(destDir, ".git", "info", "exclude");
|
|
38685
39200
|
try {
|
|
38686
39201
|
const existing = existsSync13(excludeFile) ? readFileSync15(excludeFile, "utf8") : "";
|
|
38687
39202
|
if (!existing.split("\n").includes(BRIEF_EXCLUDE_LINE)) {
|
|
38688
|
-
|
|
38689
|
-
|
|
39203
|
+
mkdirSync8(dirname9(excludeFile), { recursive: true });
|
|
39204
|
+
writeFileSync17(
|
|
38690
39205
|
excludeFile,
|
|
38691
39206
|
`${existing}${existing === "" || existing.endsWith("\n") ? "" : "\n"}${BRIEF_EXCLUDE_LINE}
|
|
38692
39207
|
`,
|
|
@@ -38700,9 +39215,9 @@ function ensureExcludedPackDir(destDir) {
|
|
|
38700
39215
|
}
|
|
38701
39216
|
function writePackFile(destDir, relPath, content, what) {
|
|
38702
39217
|
try {
|
|
38703
|
-
const abs =
|
|
38704
|
-
|
|
38705
|
-
|
|
39218
|
+
const abs = join30(destDir, relPath);
|
|
39219
|
+
mkdirSync8(dirname9(abs), { recursive: true });
|
|
39220
|
+
writeFileSync17(abs, content, { encoding: "utf8", flag: "wx" });
|
|
38706
39221
|
} catch (err) {
|
|
38707
39222
|
return { written: false, reason: `the ${what} could not be written (${err.message})` };
|
|
38708
39223
|
}
|
|
@@ -39103,7 +39618,7 @@ async function cmdSliceFullTier(claims, id, local, fullTierBody, flags, cloneRep
|
|
|
39103
39618
|
if (resolvedDir.suffixed) {
|
|
39104
39619
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${dest}`);
|
|
39105
39620
|
}
|
|
39106
|
-
|
|
39621
|
+
mkdirSync8(dest, { recursive: true });
|
|
39107
39622
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
39108
39623
|
let engine;
|
|
39109
39624
|
try {
|
|
@@ -39285,7 +39800,7 @@ async function attemptSliceDelivery(id, flags = {}) {
|
|
|
39285
39800
|
if (resolvedDir.suffixed) {
|
|
39286
39801
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${finalDest}`);
|
|
39287
39802
|
}
|
|
39288
|
-
|
|
39803
|
+
mkdirSync8(dirname9(finalDest), { recursive: true });
|
|
39289
39804
|
let dest = mkdtempSync5(`${finalDest}.tmp-`);
|
|
39290
39805
|
const { written, unavailable } = writeSliceFiles(dest, body.files);
|
|
39291
39806
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
@@ -39826,7 +40341,7 @@ async function cmdSubmit(id, flags = {}) {
|
|
|
39826
40341
|
const head = `${ghUser}:${claim.branch}`;
|
|
39827
40342
|
const title = flags.title || claim.title;
|
|
39828
40343
|
const noBody = Boolean(flags["no-body"]);
|
|
39829
|
-
const prBodyPath =
|
|
40344
|
+
const prBodyPath = join30(wt, "PR-BODY.md");
|
|
39830
40345
|
const bodySource = pickBodySource({
|
|
39831
40346
|
bodyFileFlag: flags["body-file"],
|
|
39832
40347
|
noBody,
|
|
@@ -40066,7 +40581,7 @@ function readClaimPushMarker() {
|
|
|
40066
40581
|
}
|
|
40067
40582
|
function writeClaimPushMarker(marker) {
|
|
40068
40583
|
ensureStateDir(TERMINALHIRE_DIR11);
|
|
40069
|
-
|
|
40584
|
+
writeFileSync17(CLAIM_PUSH_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
40070
40585
|
}
|
|
40071
40586
|
function clearClaimPushMarker() {
|
|
40072
40587
|
try {
|
|
@@ -40980,10 +41495,10 @@ var init_jpi_claim = __esm({
|
|
|
40980
41495
|
init_claim_push_bg();
|
|
40981
41496
|
init_founder_verdict_sync();
|
|
40982
41497
|
init_founder_note_sync();
|
|
40983
|
-
TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR ||
|
|
40984
|
-
INDEX_CACHE_FILE2 =
|
|
40985
|
-
CLAIM_PUSH_MARKER =
|
|
40986
|
-
REPO_CONTINUITY_NUDGE_MARKER =
|
|
41498
|
+
TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR || join30(homedir15(), ".terminalhire");
|
|
41499
|
+
INDEX_CACHE_FILE2 = join30(TERMINALHIRE_DIR11, "index-cache.json");
|
|
41500
|
+
CLAIM_PUSH_MARKER = join30(TERMINALHIRE_DIR11, "claim-push.json");
|
|
41501
|
+
REPO_CONTINUITY_NUDGE_MARKER = join30(TERMINALHIRE_DIR11, "repo-continuity-nudged.json");
|
|
40987
41502
|
API_URL = resolveApiBase();
|
|
40988
41503
|
CLAIM_SYNC_BASE4 = API_URL;
|
|
40989
41504
|
CLAIM_CONSENT_VERSION = 1;
|
|
@@ -53227,9 +53742,9 @@ var require_schemes = __commonJS({
|
|
|
53227
53742
|
wsComponent.secure = void 0;
|
|
53228
53743
|
}
|
|
53229
53744
|
if (wsComponent.resourceName) {
|
|
53230
|
-
const [path5,
|
|
53745
|
+
const [path5, query2] = wsComponent.resourceName.split("?");
|
|
53231
53746
|
wsComponent.path = path5 && path5 !== "/" ? path5 : void 0;
|
|
53232
|
-
wsComponent.query =
|
|
53747
|
+
wsComponent.query = query2;
|
|
53233
53748
|
wsComponent.resourceName = void 0;
|
|
53234
53749
|
}
|
|
53235
53750
|
wsComponent.fragment = void 0;
|
|
@@ -63184,8 +63699,8 @@ __export(config_exports, {
|
|
|
63184
63699
|
readConfig: () => readConfig,
|
|
63185
63700
|
writeConfig: () => writeConfig
|
|
63186
63701
|
});
|
|
63187
|
-
import { readFileSync as readFileSync16, writeFileSync as
|
|
63188
|
-
import { join as
|
|
63702
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync18, existsSync as existsSync14 } from "fs";
|
|
63703
|
+
import { join as join31 } from "path";
|
|
63189
63704
|
import { homedir as homedir16 } from "os";
|
|
63190
63705
|
function readConfig() {
|
|
63191
63706
|
try {
|
|
@@ -63207,7 +63722,7 @@ function writeConfig(config2) {
|
|
|
63207
63722
|
}
|
|
63208
63723
|
delete merged.contributePrompted;
|
|
63209
63724
|
}
|
|
63210
|
-
|
|
63725
|
+
writeFileSync18(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
63211
63726
|
}
|
|
63212
63727
|
function parseNudgeMode(raw) {
|
|
63213
63728
|
if (raw === "session" || raw === "always") return raw;
|
|
@@ -63268,8 +63783,8 @@ var init_config = __esm({
|
|
|
63268
63783
|
"src/config.ts"() {
|
|
63269
63784
|
"use strict";
|
|
63270
63785
|
init_state_dir();
|
|
63271
|
-
TERMINALHIRE_DIR12 = process.env.TERMINALHIRE_DIR ||
|
|
63272
|
-
CONFIG_FILE =
|
|
63786
|
+
TERMINALHIRE_DIR12 = process.env.TERMINALHIRE_DIR || join31(homedir16(), ".terminalhire");
|
|
63787
|
+
CONFIG_FILE = join31(TERMINALHIRE_DIR12, "config.json");
|
|
63273
63788
|
DEFAULT_CONFIG = {
|
|
63274
63789
|
nudge: "session",
|
|
63275
63790
|
peerConnect: false,
|
|
@@ -63773,7 +64288,7 @@ async function claimWorkspaceResult(args = {}) {
|
|
|
63773
64288
|
try {
|
|
63774
64289
|
const claims = await Promise.resolve().then(() => (init_claims(), claims_exports));
|
|
63775
64290
|
const { existsSync: existsSync15, readFileSync: readFileSync17, lstatSync: lstatSync4 } = await import("fs");
|
|
63776
|
-
const { join:
|
|
64291
|
+
const { join: join32 } = await import("path");
|
|
63777
64292
|
const { BRIEF_REL_PATH: BRIEF_REL_PATH2, VERIFY_REL_PATH: VERIFY_REL_PATH2, AGENTS_REL_PATH: AGENTS_REL_PATH2, sha256OfUtf8: sha256OfUtf82 } = await Promise.resolve().then(() => (init_jpi_claim(), jpi_claim_exports));
|
|
63778
64293
|
const packPaths = (c) => {
|
|
63779
64294
|
const p = {};
|
|
@@ -63786,7 +64301,7 @@ async function claimWorkspaceResult(args = {}) {
|
|
|
63786
64301
|
if (c.workspacePack?.[member] !== true) continue;
|
|
63787
64302
|
const digest = c.packDigests?.[member];
|
|
63788
64303
|
if (typeof digest !== "string" || digest === "") continue;
|
|
63789
|
-
const abs =
|
|
64304
|
+
const abs = join32(c.worktreePath, rel);
|
|
63790
64305
|
try {
|
|
63791
64306
|
const st = lstatSync4(abs);
|
|
63792
64307
|
if (!st.isFile() || st.size > 1024 * 1024) continue;
|
|
@@ -63805,7 +64320,7 @@ async function claimWorkspaceResult(args = {}) {
|
|
|
63805
64320
|
hint: `No workspace has been delivered for this claim yet. A human runs: terminalhire claim start ${c.id} --watch`
|
|
63806
64321
|
};
|
|
63807
64322
|
}
|
|
63808
|
-
if (!existsSync15(c.worktreePath) || !existsSync15(
|
|
64323
|
+
if (!existsSync15(c.worktreePath) || !existsSync15(join32(c.worktreePath, ".git"))) {
|
|
63809
64324
|
return {
|
|
63810
64325
|
status: "not_ready",
|
|
63811
64326
|
claimId: c.id,
|
|
@@ -64011,10 +64526,10 @@ async function run2() {
|
|
|
64011
64526
|
let version2 = "0.0.0";
|
|
64012
64527
|
try {
|
|
64013
64528
|
const { readFileSync: readFileSync17, existsSync: existsSync15 } = await import("fs");
|
|
64014
|
-
const { join:
|
|
64529
|
+
const { join: join32 } = await import("path");
|
|
64015
64530
|
const { fileURLToPath: fileURLToPath4 } = await import("url");
|
|
64016
64531
|
const here = fileURLToPath4(new URL(".", import.meta.url));
|
|
64017
|
-
for (const p of [
|
|
64532
|
+
for (const p of [join32(here, "..", "..", "package.json"), join32(here, "..", "package.json")]) {
|
|
64018
64533
|
if (existsSync15(p)) {
|
|
64019
64534
|
const pkg = JSON.parse(readFileSync17(p, "utf8"));
|
|
64020
64535
|
if (pkg.version) {
|