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-claim.js
CHANGED
|
@@ -1893,11 +1893,11 @@ function parseGitHubRef(url) {
|
|
|
1893
1893
|
kind: m[3] === "pull" ? "pull" : "issue"
|
|
1894
1894
|
};
|
|
1895
1895
|
}
|
|
1896
|
-
async function ghGraphQL(
|
|
1896
|
+
async function ghGraphQL(query2, variables, token, signal, governor) {
|
|
1897
1897
|
const init = {
|
|
1898
1898
|
method: "POST",
|
|
1899
1899
|
headers: { ...ghHeaders(token), "Content-Type": "application/json" },
|
|
1900
|
-
body: JSON.stringify({ query, variables }),
|
|
1900
|
+
body: JSON.stringify({ query: query2, variables }),
|
|
1901
1901
|
signal
|
|
1902
1902
|
};
|
|
1903
1903
|
if (governor) {
|
|
@@ -12408,8 +12408,8 @@ var init_stringify = __esm({
|
|
|
12408
12408
|
});
|
|
12409
12409
|
|
|
12410
12410
|
// ../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs
|
|
12411
|
-
function stringifyQuery(
|
|
12412
|
-
return stringify(
|
|
12411
|
+
function stringifyQuery(query2) {
|
|
12412
|
+
return stringify(query2, { arrayFormat: "brackets" });
|
|
12413
12413
|
}
|
|
12414
12414
|
var init_query = __esm({
|
|
12415
12415
|
"../../node_modules/@anthropic-ai/sdk/internal/utils/query.mjs"() {
|
|
@@ -14493,9 +14493,9 @@ var init_deployment_runs = __esm({
|
|
|
14493
14493
|
* ```
|
|
14494
14494
|
*/
|
|
14495
14495
|
list(params = {}, options) {
|
|
14496
|
-
const { betas, ...
|
|
14496
|
+
const { betas, ...query2 } = params ?? {};
|
|
14497
14497
|
return this._client.getAPIList("/v1/deployment_runs?beta=true", PageCursor, {
|
|
14498
|
-
query,
|
|
14498
|
+
query: query2,
|
|
14499
14499
|
...options,
|
|
14500
14500
|
headers: buildHeaders([
|
|
14501
14501
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -14607,9 +14607,9 @@ var init_deployments = __esm({
|
|
|
14607
14607
|
* ```
|
|
14608
14608
|
*/
|
|
14609
14609
|
list(params = {}, options) {
|
|
14610
|
-
const { betas, ...
|
|
14610
|
+
const { betas, ...query2 } = params ?? {};
|
|
14611
14611
|
return this._client.getAPIList("/v1/deployments?beta=true", PageCursor, {
|
|
14612
|
-
query,
|
|
14612
|
+
query: query2,
|
|
14613
14613
|
...options,
|
|
14614
14614
|
headers: buildHeaders([
|
|
14615
14615
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -14769,9 +14769,9 @@ var init_dreams = __esm({
|
|
|
14769
14769
|
* ```
|
|
14770
14770
|
*/
|
|
14771
14771
|
list(params = {}, options) {
|
|
14772
|
-
const { betas, ...
|
|
14772
|
+
const { betas, ...query2 } = params ?? {};
|
|
14773
14773
|
return this._client.getAPIList("/v1/dreams?beta=true", PageCursor, {
|
|
14774
|
-
query,
|
|
14774
|
+
query: query2,
|
|
14775
14775
|
...options,
|
|
14776
14776
|
headers: buildHeaders([
|
|
14777
14777
|
{ "anthropic-beta": [...betas ?? [], "dreaming-2026-04-21"].toString() },
|
|
@@ -14902,9 +14902,9 @@ var init_files = __esm({
|
|
|
14902
14902
|
* ```
|
|
14903
14903
|
*/
|
|
14904
14904
|
list(params = {}, options) {
|
|
14905
|
-
const { betas, ...
|
|
14905
|
+
const { betas, ...query2 } = params ?? {};
|
|
14906
14906
|
return this._client.getAPIList("/v1/files?beta=true", Page, {
|
|
14907
|
-
query,
|
|
14907
|
+
query: query2,
|
|
14908
14908
|
...options,
|
|
14909
14909
|
headers: buildHeaders([
|
|
14910
14910
|
{ "anthropic-beta": [...betas ?? [], "files-api-2025-04-14"].toString() },
|
|
@@ -15052,9 +15052,9 @@ var init_models = __esm({
|
|
|
15052
15052
|
* ```
|
|
15053
15053
|
*/
|
|
15054
15054
|
list(params = {}, options) {
|
|
15055
|
-
const { betas, ...
|
|
15055
|
+
const { betas, ...query2 } = params ?? {};
|
|
15056
15056
|
return this._client.getAPIList("/v1/models?beta=true", Page, {
|
|
15057
|
-
query,
|
|
15057
|
+
query: query2,
|
|
15058
15058
|
...options,
|
|
15059
15059
|
headers: buildHeaders([
|
|
15060
15060
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -15151,9 +15151,9 @@ var init_user_profiles = __esm({
|
|
|
15151
15151
|
* ```
|
|
15152
15152
|
*/
|
|
15153
15153
|
list(params = {}, options) {
|
|
15154
|
-
const { betas, ...
|
|
15154
|
+
const { betas, ...query2 } = params ?? {};
|
|
15155
15155
|
return this._client.getAPIList("/v1/user_profiles?beta=true", PageCursor, {
|
|
15156
|
-
query,
|
|
15156
|
+
query: query2,
|
|
15157
15157
|
...options,
|
|
15158
15158
|
headers: buildHeaders([
|
|
15159
15159
|
{ "anthropic-beta": [...betas ?? [], "user-profiles-2026-03-24"].toString() },
|
|
@@ -16012,9 +16012,9 @@ var init_versions = __esm({
|
|
|
16012
16012
|
* ```
|
|
16013
16013
|
*/
|
|
16014
16014
|
list(agentID, params = {}, options) {
|
|
16015
|
-
const { betas, ...
|
|
16015
|
+
const { betas, ...query2 } = params ?? {};
|
|
16016
16016
|
return this._client.getAPIList(path`/v1/agents/${agentID}/versions?beta=true`, PageCursor, {
|
|
16017
|
-
query,
|
|
16017
|
+
query: query2,
|
|
16018
16018
|
...options,
|
|
16019
16019
|
headers: buildHeaders([
|
|
16020
16020
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -16077,9 +16077,9 @@ var init_agents = __esm({
|
|
|
16077
16077
|
* ```
|
|
16078
16078
|
*/
|
|
16079
16079
|
retrieve(agentID, params = {}, options) {
|
|
16080
|
-
const { betas, ...
|
|
16080
|
+
const { betas, ...query2 } = params ?? {};
|
|
16081
16081
|
return this._client.get(path`/v1/agents/${agentID}?beta=true`, {
|
|
16082
|
-
query,
|
|
16082
|
+
query: query2,
|
|
16083
16083
|
...options,
|
|
16084
16084
|
headers: buildHeaders([
|
|
16085
16085
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -16122,9 +16122,9 @@ var init_agents = __esm({
|
|
|
16122
16122
|
* ```
|
|
16123
16123
|
*/
|
|
16124
16124
|
list(params = {}, options) {
|
|
16125
|
-
const { betas, ...
|
|
16125
|
+
const { betas, ...query2 } = params ?? {};
|
|
16126
16126
|
return this._client.getAPIList("/v1/agents?beta=true", PageCursor, {
|
|
16127
|
-
query,
|
|
16127
|
+
query: query2,
|
|
16128
16128
|
...options,
|
|
16129
16129
|
headers: buildHeaders([
|
|
16130
16130
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -18214,9 +18214,9 @@ var init_work = __esm({
|
|
|
18214
18214
|
* ```
|
|
18215
18215
|
*/
|
|
18216
18216
|
list(environmentID, params = {}, options) {
|
|
18217
|
-
const { betas, ...
|
|
18217
|
+
const { betas, ...query2 } = params ?? {};
|
|
18218
18218
|
return this._client.getAPIList(path`/v1/environments/${environmentID}/work?beta=true`, PageCursor, {
|
|
18219
|
-
query,
|
|
18219
|
+
query: query2,
|
|
18220
18220
|
...options,
|
|
18221
18221
|
headers: buildHeaders([
|
|
18222
18222
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -18295,9 +18295,9 @@ var init_work = __esm({
|
|
|
18295
18295
|
* ```
|
|
18296
18296
|
*/
|
|
18297
18297
|
poll(environmentID, params = {}, options) {
|
|
18298
|
-
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...
|
|
18298
|
+
const { betas, "Anthropic-Worker-ID": anthropicWorkerID, ...query2 } = params ?? {};
|
|
18299
18299
|
return this._client.get(path`/v1/environments/${environmentID}/work/poll?beta=true`, {
|
|
18300
|
-
query,
|
|
18300
|
+
query: query2,
|
|
18301
18301
|
...options,
|
|
18302
18302
|
headers: buildHeaders([
|
|
18303
18303
|
{
|
|
@@ -18494,9 +18494,9 @@ var init_environments = __esm({
|
|
|
18494
18494
|
* ```
|
|
18495
18495
|
*/
|
|
18496
18496
|
list(params = {}, options) {
|
|
18497
|
-
const { betas, ...
|
|
18497
|
+
const { betas, ...query2 } = params ?? {};
|
|
18498
18498
|
return this._client.getAPIList("/v1/environments?beta=true", PageCursor, {
|
|
18499
|
-
query,
|
|
18499
|
+
query: query2,
|
|
18500
18500
|
...options,
|
|
18501
18501
|
headers: buildHeaders([
|
|
18502
18502
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -18599,9 +18599,9 @@ var init_memories = __esm({
|
|
|
18599
18599
|
* ```
|
|
18600
18600
|
*/
|
|
18601
18601
|
retrieve(memoryID, params, options) {
|
|
18602
|
-
const { memory_store_id, betas, ...
|
|
18602
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
18603
18603
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memories/${memoryID}?beta=true`, {
|
|
18604
|
-
query,
|
|
18604
|
+
query: query2,
|
|
18605
18605
|
...options,
|
|
18606
18606
|
headers: buildHeaders([
|
|
18607
18607
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -18647,9 +18647,9 @@ var init_memories = __esm({
|
|
|
18647
18647
|
* ```
|
|
18648
18648
|
*/
|
|
18649
18649
|
list(memoryStoreID, params = {}, options) {
|
|
18650
|
-
const { betas, ...
|
|
18650
|
+
const { betas, ...query2 } = params ?? {};
|
|
18651
18651
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memories?beta=true`, PageCursor, {
|
|
18652
|
-
query,
|
|
18652
|
+
query: query2,
|
|
18653
18653
|
...options,
|
|
18654
18654
|
headers: buildHeaders([
|
|
18655
18655
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -18707,9 +18707,9 @@ var init_memory_versions = __esm({
|
|
|
18707
18707
|
* ```
|
|
18708
18708
|
*/
|
|
18709
18709
|
retrieve(memoryVersionID, params, options) {
|
|
18710
|
-
const { memory_store_id, betas, ...
|
|
18710
|
+
const { memory_store_id, betas, ...query2 } = params;
|
|
18711
18711
|
return this._client.get(path`/v1/memory_stores/${memory_store_id}/memory_versions/${memoryVersionID}?beta=true`, {
|
|
18712
|
-
query,
|
|
18712
|
+
query: query2,
|
|
18713
18713
|
...options,
|
|
18714
18714
|
headers: buildHeaders([
|
|
18715
18715
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -18731,9 +18731,9 @@ var init_memory_versions = __esm({
|
|
|
18731
18731
|
* ```
|
|
18732
18732
|
*/
|
|
18733
18733
|
list(memoryStoreID, params = {}, options) {
|
|
18734
|
-
const { betas, ...
|
|
18734
|
+
const { betas, ...query2 } = params ?? {};
|
|
18735
18735
|
return this._client.getAPIList(path`/v1/memory_stores/${memoryStoreID}/memory_versions?beta=true`, PageCursor, {
|
|
18736
|
-
query,
|
|
18736
|
+
query: query2,
|
|
18737
18737
|
...options,
|
|
18738
18738
|
headers: buildHeaders([
|
|
18739
18739
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -18859,9 +18859,9 @@ var init_memory_stores = __esm({
|
|
|
18859
18859
|
* ```
|
|
18860
18860
|
*/
|
|
18861
18861
|
list(params = {}, options) {
|
|
18862
|
-
const { betas, ...
|
|
18862
|
+
const { betas, ...query2 } = params ?? {};
|
|
18863
18863
|
return this._client.getAPIList("/v1/memory_stores?beta=true", PageCursor, {
|
|
18864
|
-
query,
|
|
18864
|
+
query: query2,
|
|
18865
18865
|
...options,
|
|
18866
18866
|
headers: buildHeaders([
|
|
18867
18867
|
{ "anthropic-beta": [...betas ?? [], "agent-memory-2026-07-22"].toString() },
|
|
@@ -19059,9 +19059,9 @@ var init_batches = __esm({
|
|
|
19059
19059
|
* ```
|
|
19060
19060
|
*/
|
|
19061
19061
|
list(params = {}, options) {
|
|
19062
|
-
const { betas, ...
|
|
19062
|
+
const { betas, ...query2 } = params ?? {};
|
|
19063
19063
|
return this._client.getAPIList("/v1/messages/batches?beta=true", Page, {
|
|
19064
|
-
query,
|
|
19064
|
+
query: query2,
|
|
19065
19065
|
...options,
|
|
19066
19066
|
headers: buildHeaders([
|
|
19067
19067
|
{ "anthropic-beta": [...betas ?? [], "message-batches-2024-09-24"].toString() },
|
|
@@ -20734,9 +20734,9 @@ var init_events = __esm({
|
|
|
20734
20734
|
* ```
|
|
20735
20735
|
*/
|
|
20736
20736
|
list(sessionID, params = {}, options) {
|
|
20737
|
-
const { betas, ...
|
|
20737
|
+
const { betas, ...query2 } = params ?? {};
|
|
20738
20738
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/events?beta=true`, PageCursor, {
|
|
20739
|
-
query,
|
|
20739
|
+
query: query2,
|
|
20740
20740
|
...options,
|
|
20741
20741
|
headers: buildHeaders([
|
|
20742
20742
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -20791,9 +20791,9 @@ var init_events = __esm({
|
|
|
20791
20791
|
* ```
|
|
20792
20792
|
*/
|
|
20793
20793
|
stream(sessionID, params = {}, options) {
|
|
20794
|
-
const { betas, ...
|
|
20794
|
+
const { betas, ...query2 } = params ?? {};
|
|
20795
20795
|
return this._client.get(path`/v1/sessions/${sessionID}/events/stream?beta=true`, {
|
|
20796
|
-
query,
|
|
20796
|
+
query: query2,
|
|
20797
20797
|
...options,
|
|
20798
20798
|
headers: buildHeaders([
|
|
20799
20799
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -20901,9 +20901,9 @@ var init_resources = __esm({
|
|
|
20901
20901
|
* ```
|
|
20902
20902
|
*/
|
|
20903
20903
|
list(sessionID, params = {}, options) {
|
|
20904
|
-
const { betas, ...
|
|
20904
|
+
const { betas, ...query2 } = params ?? {};
|
|
20905
20905
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/resources?beta=true`, PageCursor, {
|
|
20906
|
-
query,
|
|
20906
|
+
query: query2,
|
|
20907
20907
|
...options,
|
|
20908
20908
|
headers: buildHeaders([
|
|
20909
20909
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -20988,9 +20988,9 @@ var init_events2 = __esm({
|
|
|
20988
20988
|
* ```
|
|
20989
20989
|
*/
|
|
20990
20990
|
list(threadID, params, options) {
|
|
20991
|
-
const { session_id, betas, ...
|
|
20991
|
+
const { session_id, betas, ...query2 } = params;
|
|
20992
20992
|
return this._client.getAPIList(path`/v1/sessions/${session_id}/threads/${threadID}/events?beta=true`, PageCursor, {
|
|
20993
|
-
query,
|
|
20993
|
+
query: query2,
|
|
20994
20994
|
...options,
|
|
20995
20995
|
headers: buildHeaders([
|
|
20996
20996
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21077,9 +21077,9 @@ var init_threads = __esm({
|
|
|
21077
21077
|
* ```
|
|
21078
21078
|
*/
|
|
21079
21079
|
list(sessionID, params = {}, options) {
|
|
21080
|
-
const { betas, ...
|
|
21080
|
+
const { betas, ...query2 } = params ?? {};
|
|
21081
21081
|
return this._client.getAPIList(path`/v1/sessions/${sessionID}/threads?beta=true`, PageCursor, {
|
|
21082
|
-
query,
|
|
21082
|
+
query: query2,
|
|
21083
21083
|
...options,
|
|
21084
21084
|
headers: buildHeaders([
|
|
21085
21085
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21214,9 +21214,9 @@ var init_sessions = __esm({
|
|
|
21214
21214
|
* ```
|
|
21215
21215
|
*/
|
|
21216
21216
|
list(params = {}, options) {
|
|
21217
|
-
const { betas, ...
|
|
21217
|
+
const { betas, ...query2 } = params ?? {};
|
|
21218
21218
|
return this._client.getAPIList("/v1/sessions?beta=true", BidirectionalPageCursor, {
|
|
21219
|
-
query,
|
|
21219
|
+
query: query2,
|
|
21220
21220
|
...options,
|
|
21221
21221
|
headers: buildHeaders([
|
|
21222
21222
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -21341,9 +21341,9 @@ var init_versions2 = __esm({
|
|
|
21341
21341
|
* ```
|
|
21342
21342
|
*/
|
|
21343
21343
|
list(skillID, params = {}, options) {
|
|
21344
|
-
const { betas, ...
|
|
21344
|
+
const { betas, ...query2 } = params ?? {};
|
|
21345
21345
|
return this._client.getAPIList(path`/v1/skills/${skillID}/versions?beta=true`, PageCursor, {
|
|
21346
|
-
query,
|
|
21346
|
+
query: query2,
|
|
21347
21347
|
...options,
|
|
21348
21348
|
headers: buildHeaders([
|
|
21349
21349
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -21472,9 +21472,9 @@ var init_skills2 = __esm({
|
|
|
21472
21472
|
* ```
|
|
21473
21473
|
*/
|
|
21474
21474
|
list(params = {}, options) {
|
|
21475
|
-
const { betas, ...
|
|
21475
|
+
const { betas, ...query2 } = params ?? {};
|
|
21476
21476
|
return this._client.getAPIList("/v1/skills?beta=true", PageCursor, {
|
|
21477
|
-
query,
|
|
21477
|
+
query: query2,
|
|
21478
21478
|
...options,
|
|
21479
21479
|
headers: buildHeaders([
|
|
21480
21480
|
{ "anthropic-beta": [...betas ?? [], "skills-2025-10-02"].toString() },
|
|
@@ -21592,9 +21592,9 @@ var init_certificates = __esm({
|
|
|
21592
21592
|
* ```
|
|
21593
21593
|
*/
|
|
21594
21594
|
list(tunnelID, params = {}, options) {
|
|
21595
|
-
const { betas, ...
|
|
21595
|
+
const { betas, ...query2 } = params ?? {};
|
|
21596
21596
|
return this._client.getAPIList(path`/v1/tunnels/${tunnelID}/certificates?beta=true`, PageCursor, {
|
|
21597
|
-
query,
|
|
21597
|
+
query: query2,
|
|
21598
21598
|
...options,
|
|
21599
21599
|
headers: buildHeaders([
|
|
21600
21600
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -21721,9 +21721,9 @@ var init_tunnels = __esm({
|
|
|
21721
21721
|
* ```
|
|
21722
21722
|
*/
|
|
21723
21723
|
list(params = {}, options) {
|
|
21724
|
-
const { betas, ...
|
|
21724
|
+
const { betas, ...query2 } = params ?? {};
|
|
21725
21725
|
return this._client.getAPIList("/v1/tunnels?beta=true", PageCursor, {
|
|
21726
|
-
query,
|
|
21726
|
+
query: query2,
|
|
21727
21727
|
...options,
|
|
21728
21728
|
headers: buildHeaders([
|
|
21729
21729
|
{ "anthropic-beta": [...betas ?? [], "mcp-tunnels-2026-06-22"].toString() },
|
|
@@ -21917,9 +21917,9 @@ var init_credentials2 = __esm({
|
|
|
21917
21917
|
* ```
|
|
21918
21918
|
*/
|
|
21919
21919
|
list(vaultID, params = {}, options) {
|
|
21920
|
-
const { betas, ...
|
|
21920
|
+
const { betas, ...query2 } = params ?? {};
|
|
21921
21921
|
return this._client.getAPIList(path`/v1/vaults/${vaultID}/credentials?beta=true`, PageCursor, {
|
|
21922
|
-
query,
|
|
21922
|
+
query: query2,
|
|
21923
21923
|
...options,
|
|
21924
21924
|
headers: buildHeaders([
|
|
21925
21925
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -22090,9 +22090,9 @@ var init_vaults = __esm({
|
|
|
22090
22090
|
* ```
|
|
22091
22091
|
*/
|
|
22092
22092
|
list(params = {}, options) {
|
|
22093
|
-
const { betas, ...
|
|
22093
|
+
const { betas, ...query2 } = params ?? {};
|
|
22094
22094
|
return this._client.getAPIList("/v1/vaults?beta=true", PageCursor, {
|
|
22095
|
-
query,
|
|
22095
|
+
query: query2,
|
|
22096
22096
|
...options,
|
|
22097
22097
|
headers: buildHeaders([
|
|
22098
22098
|
{ "anthropic-beta": [...betas ?? [], "managed-agents-2026-04-01"].toString() },
|
|
@@ -22978,8 +22978,8 @@ var init_batches2 = __esm({
|
|
|
22978
22978
|
* }
|
|
22979
22979
|
* ```
|
|
22980
22980
|
*/
|
|
22981
|
-
list(
|
|
22982
|
-
return this._client.getAPIList("/v1/messages/batches", Page, { query, ...options });
|
|
22981
|
+
list(query2 = {}, options) {
|
|
22982
|
+
return this._client.getAPIList("/v1/messages/batches", Page, { query: query2, ...options });
|
|
22983
22983
|
}
|
|
22984
22984
|
/**
|
|
22985
22985
|
* Delete a Message Batch.
|
|
@@ -23235,9 +23235,9 @@ var init_models2 = __esm({
|
|
|
23235
23235
|
* use in the API. More recently released models are listed first.
|
|
23236
23236
|
*/
|
|
23237
23237
|
list(params = {}, options) {
|
|
23238
|
-
const { betas, ...
|
|
23238
|
+
const { betas, ...query2 } = params ?? {};
|
|
23239
23239
|
return this._client.getAPIList("/v1/models", Page, {
|
|
23240
|
-
query,
|
|
23240
|
+
query: query2,
|
|
23241
23241
|
...options,
|
|
23242
23242
|
headers: buildHeaders([
|
|
23243
23243
|
{ ...betas?.toString() != null ? { "anthropic-beta": betas?.toString() } : void 0 },
|
|
@@ -23586,8 +23586,8 @@ var init_client = __esm({
|
|
|
23586
23586
|
}
|
|
23587
23587
|
return buildHeaders([{ Authorization: `Bearer ${this.authToken}` }]);
|
|
23588
23588
|
}
|
|
23589
|
-
stringifyQuery(
|
|
23590
|
-
return stringifyQuery(
|
|
23589
|
+
stringifyQuery(query2) {
|
|
23590
|
+
return stringifyQuery(query2);
|
|
23591
23591
|
}
|
|
23592
23592
|
getUserAgent() {
|
|
23593
23593
|
return `${this.constructor.name}/JS ${VERSION}`;
|
|
@@ -23598,16 +23598,16 @@ var init_client = __esm({
|
|
|
23598
23598
|
makeStatusError(status, error, message, headers) {
|
|
23599
23599
|
return APIError.generate(status, error, message, headers);
|
|
23600
23600
|
}
|
|
23601
|
-
buildURL(path5,
|
|
23601
|
+
buildURL(path5, query2, defaultBaseURL) {
|
|
23602
23602
|
const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
23603
23603
|
const url = isAbsoluteURL(path5) ? new URL(path5) : new URL(baseURL + (baseURL.endsWith("/") && path5.startsWith("/") ? path5.slice(1) : path5));
|
|
23604
23604
|
const defaultQuery = this.defaultQuery();
|
|
23605
23605
|
const pathQuery = Object.fromEntries(url.searchParams);
|
|
23606
23606
|
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
|
|
23607
|
-
|
|
23607
|
+
query2 = { ...pathQuery, ...defaultQuery, ...query2 };
|
|
23608
23608
|
}
|
|
23609
|
-
if (typeof
|
|
23610
|
-
url.search = this.stringifyQuery(
|
|
23609
|
+
if (typeof query2 === "object" && query2 && !Array.isArray(query2)) {
|
|
23610
|
+
url.search = this.stringifyQuery(query2);
|
|
23611
23611
|
}
|
|
23612
23612
|
return url.toString();
|
|
23613
23613
|
}
|
|
@@ -23920,14 +23920,14 @@ var init_client = __esm({
|
|
|
23920
23920
|
}
|
|
23921
23921
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
23922
23922
|
const options = { ...inputOptions };
|
|
23923
|
-
const { method, path: path5, query, defaultBaseURL } = options;
|
|
23923
|
+
const { method, path: path5, query: query2, defaultBaseURL } = options;
|
|
23924
23924
|
if (this._authState.resolution) {
|
|
23925
23925
|
await this._authState.resolution;
|
|
23926
23926
|
}
|
|
23927
23927
|
if (!this._baseURLIsExplicit && this._authState.baseURL && this.baseURL !== this._authState.baseURL) {
|
|
23928
23928
|
this.baseURL = this._authState.baseURL;
|
|
23929
23929
|
}
|
|
23930
|
-
const url = this.buildURL(path5,
|
|
23930
|
+
const url = this.buildURL(path5, query2, defaultBaseURL);
|
|
23931
23931
|
if ("timeout" in options)
|
|
23932
23932
|
validatePositiveInteger("timeout", options.timeout);
|
|
23933
23933
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -24045,8 +24045,8 @@ function stripFallbackBlocks(body) {
|
|
|
24045
24045
|
function betaRefusalFallbackMiddleware(fallbacks, options = {}) {
|
|
24046
24046
|
let warnedMissingState = false;
|
|
24047
24047
|
return async (request, next, ctx) => {
|
|
24048
|
-
const [path5,
|
|
24049
|
-
if (fallbacks.length === 0 || ctx.options?.method !== "post" || path5 !== "/v1/messages" || new URLSearchParams(
|
|
24048
|
+
const [path5, query2] = (ctx.options?.path ?? "").split("?");
|
|
24049
|
+
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) {
|
|
24050
24050
|
return next(request);
|
|
24051
24051
|
}
|
|
24052
24052
|
if (ctx.options.body.fallbacks != null) {
|
|
@@ -26050,7 +26050,7 @@ ${facts.stderr}`))
|
|
|
26050
26050
|
return null;
|
|
26051
26051
|
}
|
|
26052
26052
|
function isCommandUnavailable(facts, countsRead) {
|
|
26053
|
-
if (facts.exitCode === 127 || facts.exitCode === 126)
|
|
26053
|
+
if (facts.exitCode === 127 || facts.exitCode === 126 || facts.exitCode === 125)
|
|
26054
26054
|
return true;
|
|
26055
26055
|
if (countsRead)
|
|
26056
26056
|
return false;
|
|
@@ -26058,6 +26058,22 @@ function isCommandUnavailable(facts, countsRead) {
|
|
|
26058
26058
|
return false;
|
|
26059
26059
|
return facts.stdout.trim().length === 0 && EXEC_FAILURE.test(facts.stderr);
|
|
26060
26060
|
}
|
|
26061
|
+
function isOfflineBuildGap(facts, counts) {
|
|
26062
|
+
if (facts.runtime !== "jvm")
|
|
26063
|
+
return null;
|
|
26064
|
+
if (counts !== null && counts.tests_failed > 0)
|
|
26065
|
+
return null;
|
|
26066
|
+
if (facts.exitCode === 0 || facts.exitCode === null)
|
|
26067
|
+
return null;
|
|
26068
|
+
const out = `${facts.stdout}
|
|
26069
|
+
${facts.stderr}`;
|
|
26070
|
+
for (const pattern of OFFLINE_BUILD_GAP) {
|
|
26071
|
+
const hit = pattern.exec(out);
|
|
26072
|
+
if (hit)
|
|
26073
|
+
return hit[0];
|
|
26074
|
+
}
|
|
26075
|
+
return null;
|
|
26076
|
+
}
|
|
26061
26077
|
function classifyVerification(facts) {
|
|
26062
26078
|
if (facts.timedOut) {
|
|
26063
26079
|
return {
|
|
@@ -26082,6 +26098,14 @@ function classifyVerification(facts) {
|
|
|
26082
26098
|
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.`
|
|
26083
26099
|
};
|
|
26084
26100
|
}
|
|
26101
|
+
const gap = isOfflineBuildGap(facts, counts);
|
|
26102
|
+
if (gap !== null) {
|
|
26103
|
+
return {
|
|
26104
|
+
outcome: "test-command-unavailable",
|
|
26105
|
+
counts,
|
|
26106
|
+
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.`
|
|
26107
|
+
};
|
|
26108
|
+
}
|
|
26085
26109
|
if (counts !== null) {
|
|
26086
26110
|
if (counts.tests_failed > 0) {
|
|
26087
26111
|
return {
|
|
@@ -26136,10 +26160,19 @@ function isGreen(outcome) {
|
|
|
26136
26160
|
function isOurFault(outcome) {
|
|
26137
26161
|
return outcome === "test-command-unavailable" || outcome === "counts-unparsed";
|
|
26138
26162
|
}
|
|
26139
|
-
var int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE;
|
|
26163
|
+
var VERIFICATION_OUTCOMES, int, withSuiteFailures, READERS, SUPPORTED_RUNNERS, COVERAGE_TABLE, EXEC_FAILURE, SUITE_REPORTED_FAILURE, OFFLINE_BUILD_GAP;
|
|
26140
26164
|
var init_classify2 = __esm({
|
|
26141
26165
|
"../../packages/envrun/dist/classify.js"() {
|
|
26142
26166
|
"use strict";
|
|
26167
|
+
VERIFICATION_OUTCOMES = [
|
|
26168
|
+
"completed",
|
|
26169
|
+
"tests-failed",
|
|
26170
|
+
"no-tests-observed",
|
|
26171
|
+
"counts-unparsed",
|
|
26172
|
+
"test-command-unavailable",
|
|
26173
|
+
"environment-exhausted",
|
|
26174
|
+
"budget-exceeded"
|
|
26175
|
+
];
|
|
26143
26176
|
int = (m, i = 1) => m ? Number(m[i]) : 0;
|
|
26144
26177
|
withSuiteFailures = (counts, suiteLine) => {
|
|
26145
26178
|
if (counts.tests_failed > 0 || !suiteLine)
|
|
@@ -26239,6 +26272,51 @@ var init_classify2 = __esm({
|
|
|
26239
26272
|
return { tests_passed: int(passed), tests_failed: int(failed) + int(errors) };
|
|
26240
26273
|
}
|
|
26241
26274
|
},
|
|
26275
|
+
{
|
|
26276
|
+
// Maven surefire's per-module summary (TERM-1122), measured against surefire
|
|
26277
|
+
// 3.2.5 through `th run`:
|
|
26278
|
+
//
|
|
26279
|
+
// [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
|
|
26280
|
+
//
|
|
26281
|
+
// The per-CLASS lines carry the same counts followed by `, Time elapsed: …`, so
|
|
26282
|
+
// the end anchor after `Skipped` is what keeps them out; counting both would
|
|
26283
|
+
// double every test. One summary prints per module, so they are SUMMED. An
|
|
26284
|
+
// error is a test that could not run to an assertion, counted as failed so a
|
|
26285
|
+
// green verdict is impossible while one is outstanding, as pytest's are.
|
|
26286
|
+
runner: "maven surefire",
|
|
26287
|
+
read: (out) => {
|
|
26288
|
+
const lines = [
|
|
26289
|
+
...out.matchAll(/^(?:\[(?:INFO|WARNING|ERROR)\] )?Tests run: (\d+), Failures: (\d+), Errors: (\d+), Skipped: (\d+)(?:, Flakes: \d+)?\s*$/gm)
|
|
26290
|
+
];
|
|
26291
|
+
if (lines.length === 0)
|
|
26292
|
+
return null;
|
|
26293
|
+
let passed = 0;
|
|
26294
|
+
let failed = 0;
|
|
26295
|
+
for (const m of lines) {
|
|
26296
|
+
const [run2, failures, errors, skipped] = [m[1], m[2], m[3], m[4]].map(Number);
|
|
26297
|
+
failed += failures + errors;
|
|
26298
|
+
passed += Math.max(0, run2 - failures - errors - skipped);
|
|
26299
|
+
}
|
|
26300
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
26301
|
+
}
|
|
26302
|
+
},
|
|
26303
|
+
{
|
|
26304
|
+
// Gradle prints no test counts when every test passes, so envrun installs an
|
|
26305
|
+
// init script that prints one line per Test task (`gradleTestSummary.ts`,
|
|
26306
|
+
// TERM-1122). The marker is ours; its format is fixed there.
|
|
26307
|
+
runner: "gradle",
|
|
26308
|
+
read: (out) => {
|
|
26309
|
+
const lines = [
|
|
26310
|
+
...out.matchAll(/^terminalhire-gradle-tests: task=\S+ total=(\d+) passed=(\d+) failed=(\d+) skipped=(\d+)\s*$/gm)
|
|
26311
|
+
];
|
|
26312
|
+
if (lines.length === 0)
|
|
26313
|
+
return null;
|
|
26314
|
+
return {
|
|
26315
|
+
tests_passed: lines.reduce((sum, m) => sum + Number(m[2]), 0),
|
|
26316
|
+
tests_failed: lines.reduce((sum, m) => sum + Number(m[3]), 0)
|
|
26317
|
+
};
|
|
26318
|
+
}
|
|
26319
|
+
},
|
|
26242
26320
|
{
|
|
26243
26321
|
// mocha: ` 440 passing (1s)` and ` 2 failing`
|
|
26244
26322
|
runner: "mocha",
|
|
@@ -26273,6 +26351,79 @@ var init_classify2 = __esm({
|
|
|
26273
26351
|
const p = int(passed);
|
|
26274
26352
|
return { tests_passed: p, tests_failed: Math.max(0, t - p) };
|
|
26275
26353
|
}
|
|
26354
|
+
},
|
|
26355
|
+
{
|
|
26356
|
+
/**
|
|
26357
|
+
* BARE TAP — assertion lines with no plan and no summary comment (TERM-1138).
|
|
26358
|
+
*
|
|
26359
|
+
* LAST ON PURPOSE. It is the loosest reader here, so anything that a more specific
|
|
26360
|
+
* one can read must reach that one first: `node --test` and node-tap both emit `ok`
|
|
26361
|
+
* lines AND a closing summary, and their readers are ordered above for that reason.
|
|
26362
|
+
* Moving this up would have it answer for both.
|
|
26363
|
+
*
|
|
26364
|
+
* A hand-rolled harness prints neither summary — it emits its assertions and stops.
|
|
26365
|
+
* That is what morebetterltd/wheelhouse does: thirty `ok N - …` lines, exit 0, and
|
|
26366
|
+
* before this every one of those runs reported `counts-unparsed`, which the claim
|
|
26367
|
+
* page renders as "RESULT UNREADABLE — THE SUITE EXITED 0" over a suite that passed.
|
|
26368
|
+
*
|
|
26369
|
+
* ON THE MISSING PLAN LINE. TAP requires `1..N` so a reader can tell a finished
|
|
26370
|
+
* stream from a truncated one, and there is none here, so this cannot prove the
|
|
26371
|
+
* suite reached its end. That is a real limit and it is NOT a reason to refuse,
|
|
26372
|
+
* because it holds this format to a standard no reader in this file meets — the
|
|
26373
|
+
* jest reader greps a line out of stdout that a repository could `echo` without
|
|
26374
|
+
* running anything. These are format adapters, not a trust boundary; the boundary
|
|
26375
|
+
* is that the command is the repository's own or is refused a signature.
|
|
26376
|
+
*
|
|
26377
|
+
* CONTIGUOUS FROM 1, which buys self-consistency rather than security:
|
|
26378
|
+
*
|
|
26379
|
+
* - starting at 1 rejects a TRUNCATION. `testOutputTail` keeps the last lines, so
|
|
26380
|
+
* a stream beginning `ok 47` is the middle of a longer run and counting it would
|
|
26381
|
+
* report three tests for a suite that ran fifty.
|
|
26382
|
+
* - no gaps rejects prose that happens to carry the word, and a stream interleaved
|
|
26383
|
+
* with another's.
|
|
26384
|
+
* - anchored with no leading space rejects TAP SUBTESTS, which indent. Counting
|
|
26385
|
+
* those would double them against their parent.
|
|
26386
|
+
*/
|
|
26387
|
+
runner: "bare TAP",
|
|
26388
|
+
read: (out) => {
|
|
26389
|
+
let n = 0;
|
|
26390
|
+
let failed = 0;
|
|
26391
|
+
let passed = 0;
|
|
26392
|
+
let plan = null;
|
|
26393
|
+
for (const line of out.split("\n")) {
|
|
26394
|
+
if (/^Bail out!/.test(line))
|
|
26395
|
+
return null;
|
|
26396
|
+
const p = /^(\d+)\.\.(\d+)\s*$/.exec(line);
|
|
26397
|
+
if (p) {
|
|
26398
|
+
const declared = Number(p[2]) - Number(p[1]) + 1;
|
|
26399
|
+
if (plan !== null && plan !== declared)
|
|
26400
|
+
return null;
|
|
26401
|
+
plan = declared;
|
|
26402
|
+
continue;
|
|
26403
|
+
}
|
|
26404
|
+
const m = /^(not )?ok (\d+)(?:\s|$)/.exec(line);
|
|
26405
|
+
if (!m)
|
|
26406
|
+
continue;
|
|
26407
|
+
if (Number(m[2]) !== n + 1)
|
|
26408
|
+
return null;
|
|
26409
|
+
n += 1;
|
|
26410
|
+
const directive = /#\s*(skip|todo)\b/i.exec(line);
|
|
26411
|
+
const kind = directive?.[1]?.toLowerCase();
|
|
26412
|
+
if (kind === "skip")
|
|
26413
|
+
continue;
|
|
26414
|
+
if (m[1] !== void 0) {
|
|
26415
|
+
if (kind !== "todo")
|
|
26416
|
+
failed += 1;
|
|
26417
|
+
continue;
|
|
26418
|
+
}
|
|
26419
|
+
passed += 1;
|
|
26420
|
+
}
|
|
26421
|
+
if (n === 0)
|
|
26422
|
+
return null;
|
|
26423
|
+
if (plan !== null && plan !== n)
|
|
26424
|
+
return null;
|
|
26425
|
+
return { tests_passed: passed, tests_failed: failed };
|
|
26426
|
+
}
|
|
26276
26427
|
}
|
|
26277
26428
|
];
|
|
26278
26429
|
SUPPORTED_RUNNERS = READERS.map((r) => r.runner);
|
|
@@ -26294,6 +26445,21 @@ var init_classify2 = __esm({
|
|
|
26294
26445
|
"\\d+\\s+examples?,\\s+(?!0\\b)\\d+\\s+failures?"
|
|
26295
26446
|
// rspec's summary line
|
|
26296
26447
|
].join("|"), "m");
|
|
26448
|
+
OFFLINE_BUILD_GAP = [
|
|
26449
|
+
// Maven, `-o`: `Cannot access central (…) in offline mode and the artifact … has
|
|
26450
|
+
// not been downloaded from it before.`
|
|
26451
|
+
/in offline mode and the artifact \S+ has not been downloaded from it before/,
|
|
26452
|
+
// Maven without `-o`, as a CI-derived `mvn test` runs: it tries the network.
|
|
26453
|
+
/Could not transfer artifact \S+ from\/to /,
|
|
26454
|
+
/Plugin \S+ or one of its dependencies could not be resolved/,
|
|
26455
|
+
// Gradle, `--offline`.
|
|
26456
|
+
/No cached version (?:listing )?(?:of|for) \S+ available for offline mode/,
|
|
26457
|
+
// Gradle without `--offline`, and the wrapper fetching its own distribution.
|
|
26458
|
+
/Could not GET 'https?:\/\//,
|
|
26459
|
+
/^Downloading https:\/\/services\.gradle\.org\/distributions\//m,
|
|
26460
|
+
/No matching toolchains found for requested specification/,
|
|
26461
|
+
/Cannot find a Java installation on your machine matching/
|
|
26462
|
+
];
|
|
26297
26463
|
}
|
|
26298
26464
|
});
|
|
26299
26465
|
|
|
@@ -26359,6 +26525,12 @@ function scrubEnv(source, opts) {
|
|
|
26359
26525
|
env["GOCACHE"] = join18(jailHome, ".cache", "go-build");
|
|
26360
26526
|
env["GOFLAGS"] = "-modcacherw";
|
|
26361
26527
|
env["CARGO_HOME"] = join18(jailHome, ".cargo");
|
|
26528
|
+
env["MAVEN_OPTS"] = `-Dmaven.repo.local=${join18(jailHome, ".m2", "repository")}`;
|
|
26529
|
+
env["GRADLE_USER_HOME"] = join18(jailHome, ".gradle");
|
|
26530
|
+
const bundle = join18(jailHome, ".bundle");
|
|
26531
|
+
env["GEM_HOME"] = bundle;
|
|
26532
|
+
env["BUNDLE_PATH"] = bundle;
|
|
26533
|
+
env["BUNDLE_APP_CONFIG"] = bundle;
|
|
26362
26534
|
const proxy = opts.proxyUrl ?? DEAD_PROXY;
|
|
26363
26535
|
env["HTTP_PROXY"] = proxy;
|
|
26364
26536
|
env["HTTPS_PROXY"] = proxy;
|
|
@@ -26659,6 +26831,31 @@ var init_egressProxy = __esm({
|
|
|
26659
26831
|
"static.crates.io",
|
|
26660
26832
|
"index.crates.io",
|
|
26661
26833
|
"crates.io",
|
|
26834
|
+
// TERM-1139. `ruby` has had an image since the mapping existed and `bundle install`
|
|
26835
|
+
// as its derived command, and this host was missing — so every ruby repo could start
|
|
26836
|
+
// and could never install. Install is the ONLY step with a network grant at all, so a
|
|
26837
|
+
// denial here is terminal, not a slow path.
|
|
26838
|
+
//
|
|
26839
|
+
// One entry, not two: `hostAllowed` is dot-anchored SUFFIX matching, so this covers
|
|
26840
|
+
// `index.rubygems.org` as well. Listing that separately would advertise the grant as
|
|
26841
|
+
// narrower than it is, which the `github.com` note below rejects for the same reason.
|
|
26842
|
+
"rubygems.org",
|
|
26843
|
+
// TERM-1139, added with the `dotnet` image mapping. `dotnet restore` fetches from
|
|
26844
|
+
// NuGet; the coupling test refuses a mapped runtime whose registry is unreachable, and
|
|
26845
|
+
// it caught this one the moment the image landed.
|
|
26846
|
+
"api.nuget.org",
|
|
26847
|
+
// TERM-1122, added with the `jvm` image mapping, each from a MEASURED denial
|
|
26848
|
+
// through `th run` (the proxy's 403 in the build's own output), not a guess:
|
|
26849
|
+
// - Maven Central, where both `mvn` and Gradle's `mavenCentral()` resolve.
|
|
26850
|
+
// - `services.gradle.org`, where a Gradle wrapper fetches its distribution.
|
|
26851
|
+
// - `release-assets.githubusercontent.com`, where that fetch LANDS. Measured
|
|
26852
|
+
// chain: services.gradle.org 307 -> github.com 302 -> this host 200. The
|
|
26853
|
+
// `github.com` note below keeps `githubusercontent.com` denied until a real
|
|
26854
|
+
// install needs it; this is that install. Only this one host: raw blobs and
|
|
26855
|
+
// `objects.githubusercontent.com` stay denied.
|
|
26856
|
+
"repo.maven.apache.org",
|
|
26857
|
+
"services.gradle.org",
|
|
26858
|
+
"release-assets.githubusercontent.com",
|
|
26662
26859
|
// Git dependencies. Approved by Eric 2026-07-22 after a live run measured the
|
|
26663
26860
|
// chokepoint working under load (20 events, 16 allowed / 4 denied by host).
|
|
26664
26861
|
//
|
|
@@ -26950,6 +27147,9 @@ function containerArgs(spec, env, opts) {
|
|
|
26950
27147
|
args.push(`--env=${k}=${url}`);
|
|
26951
27148
|
}
|
|
26952
27149
|
args.push("--env=NO_PROXY=", "--env=no_proxy=");
|
|
27150
|
+
const host = opts.net.proxyHost;
|
|
27151
|
+
const port = String(opts.net.proxyPort);
|
|
27152
|
+
args.push(`--env=JAVA_TOOL_OPTIONS=-Dhttp.proxyHost=${host} -Dhttp.proxyPort=${port} -Dhttps.proxyHost=${host} -Dhttps.proxyPort=${port} -Daether.connector.http.useSystemProperties=true`);
|
|
26953
27153
|
}
|
|
26954
27154
|
args.push("--");
|
|
26955
27155
|
args.push(validateImage(opts.image ?? DEFAULT_CONTAINER_IMAGE));
|
|
@@ -27282,7 +27482,10 @@ var init_container = __esm({
|
|
|
27282
27482
|
"http_proxy",
|
|
27283
27483
|
"https_proxy",
|
|
27284
27484
|
"NO_PROXY",
|
|
27285
|
-
"no_proxy"
|
|
27485
|
+
"no_proxy",
|
|
27486
|
+
// Carries the JVM's copy of the proxy (below), so an inherited value is dropped
|
|
27487
|
+
// for the same reason as the rest.
|
|
27488
|
+
"JAVA_TOOL_OPTIONS"
|
|
27286
27489
|
]);
|
|
27287
27490
|
WINDOWS_DRIVE_ROOT = /^[A-Za-z]:[\\/]/;
|
|
27288
27491
|
IMAGE_HOST = "(?:[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)+(?::[0-9]+)?|localhost(?::[0-9]+)?)";
|
|
@@ -27332,11 +27535,17 @@ var init_dist = __esm({
|
|
|
27332
27535
|
function censusTotal(c) {
|
|
27333
27536
|
return c.containers.length + c.volumes.length + c.networks.length;
|
|
27334
27537
|
}
|
|
27335
|
-
function
|
|
27538
|
+
function query(docker3, args) {
|
|
27336
27539
|
const res = docker3.sync([...args], { timeoutMs: 15e3 });
|
|
27337
|
-
if (res.error || res.status !== 0)
|
|
27338
|
-
|
|
27339
|
-
|
|
27540
|
+
if (res.error || res.status !== 0) {
|
|
27541
|
+
const why = res.error?.message ?? (res.stderr.trim() || `exit ${String(res.status)}`);
|
|
27542
|
+
return { ids: [], failure: `docker ${args.slice(0, 2).join(" ")}: ${why}` };
|
|
27543
|
+
}
|
|
27544
|
+
const ids2 = res.stdout.split("\n").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
27545
|
+
return { ids: ids2, failure: null };
|
|
27546
|
+
}
|
|
27547
|
+
function ids(docker3, args) {
|
|
27548
|
+
return query(docker3, args).ids;
|
|
27340
27549
|
}
|
|
27341
27550
|
function census(docker3, label) {
|
|
27342
27551
|
const filter = `label=${label}`;
|
|
@@ -27346,25 +27555,67 @@ function census(docker3, label) {
|
|
|
27346
27555
|
networks: ids(docker3, ["network", "ls", "-q", "--filter", filter])
|
|
27347
27556
|
};
|
|
27348
27557
|
}
|
|
27558
|
+
function censusReport(docker3, label) {
|
|
27559
|
+
const filter = `label=${label}`;
|
|
27560
|
+
const failures = [];
|
|
27561
|
+
const ask2 = (args) => {
|
|
27562
|
+
const q = query(docker3, args);
|
|
27563
|
+
if (q.failure !== null)
|
|
27564
|
+
failures.push(q.failure);
|
|
27565
|
+
return q.ids;
|
|
27566
|
+
};
|
|
27567
|
+
const taken = {
|
|
27568
|
+
containers: ask2(["ps", "-aq", "--filter", filter]),
|
|
27569
|
+
volumes: ask2(["volume", "ls", "-q", "--filter", filter]),
|
|
27570
|
+
networks: ask2(["network", "ls", "-q", "--filter", filter])
|
|
27571
|
+
};
|
|
27572
|
+
return failures.length === 0 ? { observed: true, census: taken, unobservedReason: null } : { observed: false, census: taken, unobservedReason: failures.join("; ") };
|
|
27573
|
+
}
|
|
27349
27574
|
function localCensus(label) {
|
|
27350
27575
|
return census(localDockerClient(), label);
|
|
27351
27576
|
}
|
|
27352
|
-
function judgeLeaks(peak, after) {
|
|
27577
|
+
function judgeLeaks(peak, after, observation) {
|
|
27353
27578
|
const labelObserved = peak.containers.length > 0;
|
|
27579
|
+
if (!observation.observed) {
|
|
27580
|
+
return {
|
|
27581
|
+
labelObserved,
|
|
27582
|
+
reaped: false,
|
|
27583
|
+
observed: false,
|
|
27584
|
+
clean: false,
|
|
27585
|
+
state: "unobserved",
|
|
27586
|
+
peak,
|
|
27587
|
+
after,
|
|
27588
|
+
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.`
|
|
27589
|
+
};
|
|
27590
|
+
}
|
|
27354
27591
|
const reaped = censusTotal(after) === 0;
|
|
27355
27592
|
let note;
|
|
27593
|
+
let state;
|
|
27356
27594
|
if (!labelObserved && reaped) {
|
|
27595
|
+
state = "inconclusive";
|
|
27357
27596
|
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.";
|
|
27358
27597
|
} else if (!labelObserved) {
|
|
27598
|
+
state = "leak";
|
|
27359
27599
|
note = "no labelled container was observed alive AND objects remain \u2014 the label wiring is wrong.";
|
|
27360
27600
|
} else if (!reaped) {
|
|
27601
|
+
state = "leak";
|
|
27361
27602
|
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)}).`;
|
|
27362
27603
|
} else {
|
|
27604
|
+
state = "clean";
|
|
27363
27605
|
note = `clean: peak ${String(peak.containers.length)} labelled container(s) observed alive, 0 labelled objects remain after teardown.`;
|
|
27364
27606
|
}
|
|
27365
|
-
return {
|
|
27607
|
+
return {
|
|
27608
|
+
labelObserved,
|
|
27609
|
+
reaped,
|
|
27610
|
+
observed: true,
|
|
27611
|
+
clean: labelObserved && reaped,
|
|
27612
|
+
state,
|
|
27613
|
+
peak,
|
|
27614
|
+
after,
|
|
27615
|
+
note
|
|
27616
|
+
};
|
|
27366
27617
|
}
|
|
27367
|
-
var RUN_LABEL_KEY, LabelWatch;
|
|
27618
|
+
var RUN_LABEL_KEY, LabelWatch, LEAK_STATES;
|
|
27368
27619
|
var init_labels = __esm({
|
|
27369
27620
|
"../../packages/envrun/dist/labels.js"() {
|
|
27370
27621
|
"use strict";
|
|
@@ -27419,6 +27670,7 @@ var init_labels = __esm({
|
|
|
27419
27670
|
return this.#samples;
|
|
27420
27671
|
}
|
|
27421
27672
|
};
|
|
27673
|
+
LEAK_STATES = ["clean", "leak", "inconclusive", "unobserved"];
|
|
27422
27674
|
}
|
|
27423
27675
|
});
|
|
27424
27676
|
|
|
@@ -27903,7 +28155,7 @@ function acquireLocalLease(runId) {
|
|
|
27903
28155
|
observed: false,
|
|
27904
28156
|
census: { containers: [], volumes: [], networks: [] },
|
|
27905
28157
|
unobservedReason: RELEASED_LEASE_CENSUS_REASON
|
|
27906
|
-
} :
|
|
28158
|
+
} : censusReport(docker3, label)),
|
|
27907
28159
|
publishPreview: (req) => startPreview({ ...req, docker: docker3 }),
|
|
27908
28160
|
release: () => {
|
|
27909
28161
|
if (released) {
|
|
@@ -28023,6 +28275,17 @@ caused by: ${frame}`;
|
|
|
28023
28275
|
}
|
|
28024
28276
|
return frames === 0 ? null : out;
|
|
28025
28277
|
}
|
|
28278
|
+
function imageVariantFor(spec) {
|
|
28279
|
+
if (spec.runtime !== "jvm")
|
|
28280
|
+
return void 0;
|
|
28281
|
+
const callsGradle = /(?:^|[\s;&|(])gradle(?=\s|$)/;
|
|
28282
|
+
return [spec.installCommand, spec.testCommand].some((c) => c != null && callsGradle.test(c)) ? "gradle" : void 0;
|
|
28283
|
+
}
|
|
28284
|
+
function shapeFor(runtime, variant) {
|
|
28285
|
+
if (runtime === "jvm" && variant === "gradle")
|
|
28286
|
+
return JVM_GRADLE_IMAGE;
|
|
28287
|
+
return RUNTIME_IMAGES[runtime];
|
|
28288
|
+
}
|
|
28026
28289
|
function atLeast(a, b) {
|
|
28027
28290
|
const left = a.split(".").map(Number);
|
|
28028
28291
|
const right = b.split(".").map(Number);
|
|
@@ -28035,19 +28298,19 @@ function atLeast(a, b) {
|
|
|
28035
28298
|
}
|
|
28036
28299
|
return true;
|
|
28037
28300
|
}
|
|
28038
|
-
function imageForRuntime(runtime, override, version) {
|
|
28301
|
+
function imageForRuntime(runtime, override, version, variant) {
|
|
28039
28302
|
if (override)
|
|
28040
28303
|
return override;
|
|
28041
|
-
const shape =
|
|
28304
|
+
const shape = shapeFor(runtime, variant);
|
|
28042
28305
|
if (!shape) {
|
|
28043
|
-
throw new RunRefusalError(`no container image is mapped for runtime ${JSON.stringify(runtime)}. Refusing to run it in the Node image: a
|
|
28306
|
+
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.`);
|
|
28044
28307
|
}
|
|
28045
28308
|
if (version === void 0 || version === null)
|
|
28046
28309
|
return unversionedImage(shape);
|
|
28047
28310
|
if (!TAG_VERSION.test(version)) {
|
|
28048
28311
|
throw new RunRefusalError(`runtime version ${JSON.stringify(version)} 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.`);
|
|
28049
28312
|
}
|
|
28050
|
-
return `${shape.repository}:${version}${shape.suffix}`;
|
|
28313
|
+
return `${shape.repository}:${shape.prefix ?? ""}${version}${shape.suffix}`;
|
|
28051
28314
|
}
|
|
28052
28315
|
function setManifestProbe(probe) {
|
|
28053
28316
|
const previous = manifestProbe;
|
|
@@ -28060,10 +28323,10 @@ function imageDefinitelyAbsent(image) {
|
|
|
28060
28323
|
return false;
|
|
28061
28324
|
return /manifest unknown|no such manifest/i.test(res.output);
|
|
28062
28325
|
}
|
|
28063
|
-
function resolvePublishedImage(image, runtime, version) {
|
|
28326
|
+
function resolvePublishedImage(image, runtime, version, variant) {
|
|
28064
28327
|
if (!imageDefinitelyAbsent(image))
|
|
28065
28328
|
return image;
|
|
28066
|
-
const shape =
|
|
28329
|
+
const shape = shapeFor(runtime, variant);
|
|
28067
28330
|
if (shape && shape.declaredIsFloor && atLeast(shape.defaultVersion, version)) {
|
|
28068
28331
|
return unversionedImage(shape);
|
|
28069
28332
|
}
|
|
@@ -28071,18 +28334,19 @@ function resolvePublishedImage(image, runtime, version) {
|
|
|
28071
28334
|
}
|
|
28072
28335
|
function resolveImageForSpec(spec, override) {
|
|
28073
28336
|
const declared = spec.runtimeVersion;
|
|
28074
|
-
const
|
|
28337
|
+
const variant = imageVariantFor(spec);
|
|
28338
|
+
const image = imageForRuntime(spec.runtime, override, declared, variant);
|
|
28075
28339
|
const constructed = (() => {
|
|
28076
28340
|
if (declared === null)
|
|
28077
28341
|
return null;
|
|
28078
28342
|
try {
|
|
28079
|
-
return imageForRuntime(spec.runtime, void 0, declared);
|
|
28343
|
+
return imageForRuntime(spec.runtime, void 0, declared, variant);
|
|
28080
28344
|
} catch {
|
|
28081
28345
|
return null;
|
|
28082
28346
|
}
|
|
28083
28347
|
})();
|
|
28084
28348
|
if (constructed !== null && image === constructed && declared !== null) {
|
|
28085
|
-
return resolvePublishedImage(image, spec.runtime, declared);
|
|
28349
|
+
return resolvePublishedImage(image, spec.runtime, declared, variant);
|
|
28086
28350
|
}
|
|
28087
28351
|
return image;
|
|
28088
28352
|
}
|
|
@@ -28109,12 +28373,22 @@ function assertVenueOwnerDeclared(lease) {
|
|
|
28109
28373
|
return;
|
|
28110
28374
|
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.");
|
|
28111
28375
|
}
|
|
28376
|
+
function refuseUnbuildableSpec(spec) {
|
|
28377
|
+
if (spec.runtime !== "jvm" || spec.installCommand !== null || spec.testCommand !== null)
|
|
28378
|
+
return;
|
|
28379
|
+
const why = spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
28380
|
+
if (why === void 0) {
|
|
28381
|
+
throw new EnvRunError("internal: a jvm spec with no test command carries no no-test-command reason");
|
|
28382
|
+
}
|
|
28383
|
+
throw new RunRefusalError(`refusing to run this repository: ${why}.`);
|
|
28384
|
+
}
|
|
28112
28385
|
async function runEnvironmentSpec(req) {
|
|
28113
28386
|
const startedAt = Date.now();
|
|
28114
28387
|
const containment = req.lease.containment;
|
|
28115
28388
|
if (containment.kind !== "container") {
|
|
28116
28389
|
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.`);
|
|
28117
28390
|
}
|
|
28391
|
+
refuseUnbuildableSpec(req.spec);
|
|
28118
28392
|
assertVenueOwnerDeclared(req.lease);
|
|
28119
28393
|
const image = resolveImageForSpec(req.spec, req.image);
|
|
28120
28394
|
const { jail, tmp } = req;
|
|
@@ -28157,9 +28431,10 @@ async function runEnvironmentSpec(req) {
|
|
|
28157
28431
|
installOk: false
|
|
28158
28432
|
};
|
|
28159
28433
|
} else if (req.spec.testCommand === null) {
|
|
28434
|
+
const why = req.spec.unresolved.find((r) => r.kind === "no-test-command")?.detail;
|
|
28160
28435
|
result = {
|
|
28161
28436
|
outcome: "no-tests-observed",
|
|
28162
|
-
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.",
|
|
28437
|
+
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}.`),
|
|
28163
28438
|
installOk: true
|
|
28164
28439
|
};
|
|
28165
28440
|
} else {
|
|
@@ -28182,7 +28457,7 @@ async function runEnvironmentSpec(req) {
|
|
|
28182
28457
|
labels,
|
|
28183
28458
|
timeoutMs: req.testTimeoutMs ?? 9e5
|
|
28184
28459
|
});
|
|
28185
|
-
const verdict = classifyVerification(toExecution(test));
|
|
28460
|
+
const verdict = classifyVerification({ ...toExecution(test), runtime: req.spec.runtime });
|
|
28186
28461
|
result = { outcome: verdict.outcome, note: verdict.reason, installOk: true };
|
|
28187
28462
|
}
|
|
28188
28463
|
} finally {
|
|
@@ -28196,6 +28471,10 @@ async function runEnvironmentSpec(req) {
|
|
|
28196
28471
|
volumes: [],
|
|
28197
28472
|
networks: []
|
|
28198
28473
|
};
|
|
28474
|
+
const observation = afterReport ?? {
|
|
28475
|
+
observed: false,
|
|
28476
|
+
unobservedReason: "the run carried no label, so there was nothing to count by"
|
|
28477
|
+
};
|
|
28199
28478
|
return {
|
|
28200
28479
|
outcome: result.outcome,
|
|
28201
28480
|
tier: "container",
|
|
@@ -28204,7 +28483,7 @@ async function runEnvironmentSpec(req) {
|
|
|
28204
28483
|
test,
|
|
28205
28484
|
installOk: result.installOk,
|
|
28206
28485
|
counts: test ? readCounts(test.stdout, test.stderr) : null,
|
|
28207
|
-
leaks: judgeLeaks(peak, after),
|
|
28486
|
+
leaks: judgeLeaks(peak, after, observation),
|
|
28208
28487
|
note: result.note,
|
|
28209
28488
|
wallMs: Date.now() - startedAt
|
|
28210
28489
|
};
|
|
@@ -28254,7 +28533,7 @@ async function runStep(containment, r) {
|
|
|
28254
28533
|
wallMs: Date.now() - startedAt
|
|
28255
28534
|
};
|
|
28256
28535
|
}
|
|
28257
|
-
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
28536
|
+
var EnvRunError, RunRefusalError, MAX_CAUSE_FRAMES, CHAIN_UNREADABLE, CHAIN_TOO_DEEP, RUNTIME_IMAGES, JVM_GRADLE_IMAGE, unversionedImage, TAG_VERSION, dockerManifestProbe, manifestProbe, MISSING_IMAGE_SHAPE;
|
|
28258
28537
|
var init_execute = __esm({
|
|
28259
28538
|
"../../packages/envrun/dist/execute.js"() {
|
|
28260
28539
|
"use strict";
|
|
@@ -28291,9 +28570,66 @@ var init_execute = __esm({
|
|
|
28291
28570
|
},
|
|
28292
28571
|
go: { repository: "golang", suffix: "-bookworm", defaultVersion: "1.23", declaredIsFloor: true },
|
|
28293
28572
|
ruby: { repository: "ruby", suffix: "-bookworm", defaultVersion: "3.3", declaredIsFloor: false },
|
|
28294
|
-
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true }
|
|
28295
|
-
|
|
28296
|
-
|
|
28573
|
+
rust: { repository: "rust", suffix: "-bookworm", defaultVersion: "1", declaredIsFloor: true },
|
|
28574
|
+
/**
|
|
28575
|
+
* TERM-1139. `dotnet` was unmapped alongside `jvm`, and the recorded reason was that
|
|
28576
|
+
* neither had "a single obvious base image (gradle vs maven, sdk vs runtime)". That
|
|
28577
|
+
* reason holds for jvm and it does NOT hold here, which is why only this half moved.
|
|
28578
|
+
*
|
|
28579
|
+
* "sdk vs runtime" answers itself: the derived commands are `dotnet restore` and
|
|
28580
|
+
* `dotnet test`, and neither exists on the runtime image. There is no second build
|
|
28581
|
+
* tool competing for the slot the way maven and gradle compete for jvm's — and since
|
|
28582
|
+
* no official image carries both of those, jvm genuinely cannot be served by one key.
|
|
28583
|
+
*
|
|
28584
|
+
* MEASURED, not chosen by tag: `mcr.microsoft.com/dotnet/sdk:8.0` carries `git` and
|
|
28585
|
+
* `dotnet` (881MB). `git` is the property the whole `image-tooling-live` test exists
|
|
28586
|
+
* for, and `eclipse-temurin:21-jdk` was rejected here for lacking it.
|
|
28587
|
+
*
|
|
28588
|
+
* The tag shape fits without touching the builder: the SDK publishes a tag per
|
|
28589
|
+
* version, so `repository:VERSION` is a real image at every version envspec can
|
|
28590
|
+
* derive, with no suffix. That is NOT true of the maven images, where the leading
|
|
28591
|
+
* tag component is maven's version and Java's sits in the suffix.
|
|
28592
|
+
*
|
|
28593
|
+
* `declaredIsFloor` is true on the same reasoning as go and rust: an SDK builds
|
|
28594
|
+
* older target frameworks, so booting 8.0 for a repo asking 6.0 is the supported
|
|
28595
|
+
* case rather than a substitution. A repo asking for something NEWER than our
|
|
28596
|
+
* default still refuses, which is where TERM-643 put that line.
|
|
28597
|
+
*/
|
|
28598
|
+
dotnet: {
|
|
28599
|
+
repository: "mcr.microsoft.com/dotnet/sdk",
|
|
28600
|
+
suffix: "",
|
|
28601
|
+
defaultVersion: "8.0",
|
|
28602
|
+
declaredIsFloor: true
|
|
28603
|
+
},
|
|
28604
|
+
/**
|
|
28605
|
+
* TERM-1122. Maven's image, and the one a Gradle WRAPPER repo gets too: the wrapper
|
|
28606
|
+
* downloads its own Gradle, so it needs a JDK and nothing else. MEASURED
|
|
28607
|
+
* 2026-09-18: `maven:3.9-eclipse-temurin-21` carries `git`, `mvn` and JDK 21 on
|
|
28608
|
+
* Ubuntu 24.04, which is why this is not `eclipse-temurin` (no `git`, rejected
|
|
28609
|
+
* under TERM-1139). The JDK sits AFTER maven's own version in the tag, hence
|
|
28610
|
+
* `prefix`, and the major is all envspec derives (`javaMajor`).
|
|
28611
|
+
*
|
|
28612
|
+
* `declaredIsFloor`: a JDK builds for older `--release` targets, so a repo asking
|
|
28613
|
+
* for 16, which has no image, runs on 21. A Gradle toolchain is stricter than a
|
|
28614
|
+
* floor and asks for its exact JDK; Gradle's refusal on the wrong one reads as
|
|
28615
|
+
* ours (`classify.ts`, `isOfflineBuildGap`), never as the repo's.
|
|
28616
|
+
*/
|
|
28617
|
+
jvm: {
|
|
28618
|
+
repository: "maven",
|
|
28619
|
+
prefix: "3.9-eclipse-temurin-",
|
|
28620
|
+
suffix: "",
|
|
28621
|
+
defaultVersion: "21",
|
|
28622
|
+
declaredIsFloor: true
|
|
28623
|
+
}
|
|
28624
|
+
};
|
|
28625
|
+
JVM_GRADLE_IMAGE = {
|
|
28626
|
+
repository: "gradle",
|
|
28627
|
+
prefix: "jdk",
|
|
28628
|
+
suffix: "",
|
|
28629
|
+
defaultVersion: "21",
|
|
28630
|
+
declaredIsFloor: true
|
|
28631
|
+
};
|
|
28632
|
+
unversionedImage = (shape) => `${shape.repository}:${shape.prefix ?? ""}${shape.defaultVersion}${shape.suffix}`;
|
|
28297
28633
|
TAG_VERSION = /^\d+(?:\.\d+){0,2}$/;
|
|
28298
28634
|
dockerManifestProbe = (image) => {
|
|
28299
28635
|
const res = spawnSync4("docker", ["manifest", "inspect", image], {
|
|
@@ -28985,14 +29321,31 @@ function answerDidItPass(r) {
|
|
|
28985
29321
|
const passed = r.status === "verified" && r.outcome !== null && isGreen(r.outcome);
|
|
28986
29322
|
return { passed, summary: renderVerdictLine(r), lookAt: r.preview?.url ?? null };
|
|
28987
29323
|
}
|
|
28988
|
-
|
|
29324
|
+
function exitCodeFor(r) {
|
|
29325
|
+
if (r.status === "refused")
|
|
29326
|
+
return 2;
|
|
29327
|
+
if (r.outcome === null)
|
|
29328
|
+
return 2;
|
|
29329
|
+
return OUTCOME_EXIT_CODES[r.outcome];
|
|
29330
|
+
}
|
|
29331
|
+
var RUN_TEST_COMMAND_SOURCES, RUN_IMAGE_SOURCES, RUN_RESULT_SCHEMA, RUN_RESULT_FIELDS, RENDER_NONE, FIELD_VIEWS, OUTCOME_EXIT_CODES;
|
|
28989
29332
|
var init_result = __esm({
|
|
28990
29333
|
"../../packages/envrun/dist/result.js"() {
|
|
28991
29334
|
"use strict";
|
|
28992
29335
|
init_dist2();
|
|
28993
29336
|
init_classify2();
|
|
28994
29337
|
init_venueDescriptor();
|
|
28995
|
-
RUN_TEST_COMMAND_SOURCES = [
|
|
29338
|
+
RUN_TEST_COMMAND_SOURCES = [
|
|
29339
|
+
...TEST_COMMAND_SOURCES,
|
|
29340
|
+
"developer-declared",
|
|
29341
|
+
"operator-declared"
|
|
29342
|
+
];
|
|
29343
|
+
RUN_IMAGE_SOURCES = [
|
|
29344
|
+
"detected",
|
|
29345
|
+
"none",
|
|
29346
|
+
"operator-declared",
|
|
29347
|
+
"developer-declared"
|
|
29348
|
+
];
|
|
28996
29349
|
RUN_RESULT_SCHEMA = "terminalhire.verification-run/1";
|
|
28997
29350
|
RUN_RESULT_FIELDS = [
|
|
28998
29351
|
"schema",
|
|
@@ -29017,7 +29370,9 @@ var init_result = __esm({
|
|
|
29017
29370
|
"preview",
|
|
29018
29371
|
"containerImage",
|
|
29019
29372
|
"containerImageDigest",
|
|
29373
|
+
"imageSource",
|
|
29020
29374
|
"leaksClean",
|
|
29375
|
+
"leakState",
|
|
29021
29376
|
"venue"
|
|
29022
29377
|
];
|
|
29023
29378
|
RENDER_NONE = null;
|
|
@@ -29049,12 +29404,42 @@ var init_result = __esm({
|
|
|
29049
29404
|
preview: (r) => r.preview === null ? null : `preview ${r.preview.url}`,
|
|
29050
29405
|
containerImage: (r) => r.containerImage === null ? null : `image ${r.containerImage}`,
|
|
29051
29406
|
containerImageDigest: (r) => r.containerImageDigest === null ? null : `image digest ${r.containerImageDigest}`,
|
|
29052
|
-
|
|
29407
|
+
// Shown only when a human chose the environment. `detected` is the ordinary case and
|
|
29408
|
+
// saying so on every run would train the reader to skip the line that matters.
|
|
29409
|
+
imageSource: (r) => r.imageSource === "detected" || r.imageSource === "none" ? null : `image source ${r.imageSource} (not signed)`,
|
|
29410
|
+
// Printed through `leakState` below, which knows WHY a false is false. Rendering both would
|
|
29411
|
+
// print the leak warning on a run where we merely could not look (TERM-1144).
|
|
29412
|
+
leaksClean: RENDER_NONE,
|
|
29413
|
+
// Silent when clean and when refused, as the boolean's line was. The two not-a-leak states
|
|
29414
|
+
// get their own sentence, because "we could not check" read as "we found a leak" is the
|
|
29415
|
+
// exact confusion this field exists to end.
|
|
29416
|
+
leakState: (r) => {
|
|
29417
|
+
switch (r.leakState) {
|
|
29418
|
+
case null:
|
|
29419
|
+
case "clean":
|
|
29420
|
+
return null;
|
|
29421
|
+
case "leak":
|
|
29422
|
+
return "WARNING labelled Docker objects survived teardown";
|
|
29423
|
+
case "inconclusive":
|
|
29424
|
+
return "leak check inconclusive \u2014 no labelled container was seen while the run was live, so finding nothing afterwards proves nothing";
|
|
29425
|
+
case "unobserved":
|
|
29426
|
+
return "leak check not taken \u2014 we could not check what was left after teardown";
|
|
29427
|
+
}
|
|
29428
|
+
},
|
|
29053
29429
|
// Absent on most runs, so it prints only when there is something to say. Silence
|
|
29054
29430
|
// here is the honest rendering of "no venue answered": a placeholder line would
|
|
29055
29431
|
// invite a reader to treat an unanswered probe as a described venue.
|
|
29056
29432
|
venue: (r) => r.venue === null ? null : renderVenueLine(r.venue)
|
|
29057
29433
|
};
|
|
29434
|
+
OUTCOME_EXIT_CODES = {
|
|
29435
|
+
completed: 0,
|
|
29436
|
+
"tests-failed": 1,
|
|
29437
|
+
"no-tests-observed": 1,
|
|
29438
|
+
"budget-exceeded": 1,
|
|
29439
|
+
"counts-unparsed": 2,
|
|
29440
|
+
"test-command-unavailable": 2,
|
|
29441
|
+
"environment-exhausted": 2
|
|
29442
|
+
};
|
|
29058
29443
|
}
|
|
29059
29444
|
});
|
|
29060
29445
|
|
|
@@ -29175,12 +29560,23 @@ function toAcceptancePredicate(pair, opts = {}) {
|
|
|
29175
29560
|
if (why !== null)
|
|
29176
29561
|
return refuse3("test-command-origin-unattested", `the ${side} run ${why}`);
|
|
29177
29562
|
}
|
|
29178
|
-
if (patched.testCommandSource === "developer-declared") {
|
|
29179
|
-
return refuse3("test-command-origin-unattested", "the developer supplied the test command (unreachable \u2014 the source rules above cover it)
|
|
29563
|
+
if (patched.testCommandSource === "developer-declared" || patched.testCommandSource === "operator-declared") {
|
|
29564
|
+
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)`);
|
|
29180
29565
|
}
|
|
29181
29566
|
if (baseline.testCommandSource !== patched.testCommandSource) {
|
|
29182
29567
|
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.`);
|
|
29183
29568
|
}
|
|
29569
|
+
for (const [side, source, image] of [
|
|
29570
|
+
["patched", patched.imageSource, patched.containerImage],
|
|
29571
|
+
["baseline", baseline.imageSource, baseline.containerImage]
|
|
29572
|
+
]) {
|
|
29573
|
+
const why = IMAGE_SOURCE_IS_SIGNABLE[source](image);
|
|
29574
|
+
if (why !== null)
|
|
29575
|
+
return refuse3("image-origin-unattested", `the ${side} run ${why}`);
|
|
29576
|
+
}
|
|
29577
|
+
if (baseline.imageSource !== patched.imageSource) {
|
|
29578
|
+
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.`);
|
|
29579
|
+
}
|
|
29184
29580
|
if (baseline.containerImage !== patched.containerImage) {
|
|
29185
29581
|
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.`);
|
|
29186
29582
|
}
|
|
@@ -29237,7 +29633,7 @@ function signRunStatement(predicate, privateKey, keyid) {
|
|
|
29237
29633
|
const statement = createAcceptanceStatement(predicate);
|
|
29238
29634
|
return { statement, envelope: signStatement(statement, privateKey, keyid) };
|
|
29239
29635
|
}
|
|
29240
|
-
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;
|
|
29636
|
+
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;
|
|
29241
29637
|
var init_attestation2 = __esm({
|
|
29242
29638
|
"../../packages/envrun/dist/attestation.js"() {
|
|
29243
29639
|
"use strict";
|
|
@@ -29293,11 +29689,25 @@ var init_attestation2 = __esm({
|
|
|
29293
29689
|
// The party under verification chose it, and no signed member can say so. Per ADR-005
|
|
29294
29690
|
// Decision 2, emit nothing rather than pick the closest word.
|
|
29295
29691
|
"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.",
|
|
29692
|
+
// US, out of band, per posting — the twin of `IMAGE_SOURCE_IS_SIGNABLE['operator-declared']`
|
|
29693
|
+
// and refusing for the same reason. `founder-declared` is the nearest signed member and it
|
|
29694
|
+
// is still false: the poster did not choose this, we did, and signing our own choice under
|
|
29695
|
+
// the counterparty's name is the specific false attribution the `developer-declared` entry
|
|
29696
|
+
// above exists to refuse. Decision 2 — emit nothing rather than pick the closest word.
|
|
29697
|
+
"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.",
|
|
29296
29698
|
// `none` means nobody chose a command, so a command beside it is a contradiction. Shadowed
|
|
29297
29699
|
// today — `thrun.ts` sets `none` only when the derived command is null, and `no-test-command`
|
|
29298
29700
|
// fires first — but that coupling runs through `runEnvironmentSpec` and lives in no type.
|
|
29299
29701
|
none: (command) => command === null ? null : `records its command source as \`none\` \u2014 nobody chose one \u2014 beside the command ${JSON.stringify(command)}`
|
|
29300
29702
|
};
|
|
29703
|
+
IMAGE_SOURCE_IS_SIGNABLE = {
|
|
29704
|
+
detected: () => null,
|
|
29705
|
+
"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.",
|
|
29706
|
+
"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.",
|
|
29707
|
+
// `none` means no image was booted, so an image name beside it is a contradiction — the
|
|
29708
|
+
// `SOURCE_IS_SIGNABLE.none` argument, applied to the other field.
|
|
29709
|
+
none: (image) => image === null ? null : `records its image source as \`none\` \u2014 nothing was booted \u2014 beside the image ${JSON.stringify(image)}`
|
|
29710
|
+
};
|
|
29301
29711
|
ATTEST_REFUSAL_REASONS = [
|
|
29302
29712
|
"our-environment-failed",
|
|
29303
29713
|
"run-was-refused",
|
|
@@ -29339,7 +29749,11 @@ var init_attestation2 = __esm({
|
|
|
29339
29749
|
// The signed triple must be reproducible from what it names — see the guard.
|
|
29340
29750
|
"patch-binding-incomplete",
|
|
29341
29751
|
"outcome-contradicts-counts",
|
|
29342
|
-
"test-command-origin-unattested"
|
|
29752
|
+
"test-command-origin-unattested",
|
|
29753
|
+
// The environment half of the pair above. `pair-disagrees-on-image` compares image NAMES;
|
|
29754
|
+
// this one asks who CHOSE the name, which no comparison of the two halves can reveal when
|
|
29755
|
+
// both were handed the same override.
|
|
29756
|
+
"image-origin-unattested"
|
|
29343
29757
|
];
|
|
29344
29758
|
refuse3 = (reason, detail) => ({
|
|
29345
29759
|
ok: false,
|
|
@@ -29843,13 +30257,20 @@ function gcpBootArgv(p) {
|
|
|
29843
30257
|
// steal". Attaching an account removes that, so the safety now rests on two things,
|
|
29844
30258
|
// and this change MUST land together with proof #2 — never ahead of it:
|
|
29845
30259
|
//
|
|
29846
|
-
// 1. `--no-scopes`
|
|
29847
|
-
// No scopes → the OAuth access-token endpoint serves nothing
|
|
29848
|
-
// TERM-706)
|
|
29849
|
-
//
|
|
29850
|
-
//
|
|
29851
|
-
//
|
|
29852
|
-
//
|
|
30260
|
+
// 1. `--no-scopes` and a NARROW grant set bound the BLAST RADIUS of a lifted
|
|
30261
|
+
// token. No scopes → the OAuth access-token endpoint serves nothing
|
|
30262
|
+
// (measured, TERM-706). This said "ZERO project roles" until 2026-09-18, and
|
|
30263
|
+
// that was never true of the account we ship: measured live, `venue-identity@`
|
|
30264
|
+
// holds `roles/confidentialcomputing.workloadUser` on the project and
|
|
30265
|
+
// `roles/artifactregistry.reader` on the `venue-images` repository alone —
|
|
30266
|
+
// the same two grants the Confidential Space note below already named, so this
|
|
30267
|
+
// file contradicted itself. Neither reaches a second repository, a bucket or
|
|
30268
|
+
// another VM, which is the property "zero roles" was reaching for. But the
|
|
30269
|
+
// token is NOT valueless: it is the attestation evidence itself, so a lifted
|
|
30270
|
+
// token still authorizes a false claim about WHERE a run happened (the
|
|
30271
|
+
// steal-a-true-token attack in the item-2 spike). `--no-scopes` stays because
|
|
30272
|
+
// it removes lateral GCP access; it does not make losing the identity token
|
|
30273
|
+
// cheap.
|
|
29853
30274
|
// 2. The untrusted code cannot reach the metadata server to lift the token at all.
|
|
29854
30275
|
// The test step runs `--network=none`; the install step runs on an `--internal`
|
|
29855
30276
|
// network whose only egress is a CONNECT-only, registry-allowlisted proxy that
|
|
@@ -31329,11 +31750,7 @@ function makeLease(p) {
|
|
|
31329
31750
|
}
|
|
31330
31751
|
try {
|
|
31331
31752
|
check("counting what the run left behind");
|
|
31332
|
-
return Promise.resolve(
|
|
31333
|
-
observed: true,
|
|
31334
|
-
census: census(p.docker, label),
|
|
31335
|
-
unobservedReason: null
|
|
31336
|
-
});
|
|
31753
|
+
return Promise.resolve(censusReport(p.docker, label));
|
|
31337
31754
|
} catch (err) {
|
|
31338
31755
|
return Promise.resolve({
|
|
31339
31756
|
observed: false,
|
|
@@ -31601,7 +32018,7 @@ function localDockerPlacement() {
|
|
|
31601
32018
|
kind: "local-docker",
|
|
31602
32019
|
refusal: null,
|
|
31603
32020
|
venue: () => localVenue(),
|
|
31604
|
-
imageFor: (runtime, override, version) => imageForRuntime(runtime, override, version)
|
|
32021
|
+
imageFor: (runtime, override, version, variant) => imageForRuntime(runtime, override, version, variant)
|
|
31605
32022
|
};
|
|
31606
32023
|
}
|
|
31607
32024
|
function hostedPoolPlacement() {
|
|
@@ -31609,7 +32026,7 @@ function hostedPoolPlacement() {
|
|
|
31609
32026
|
kind: "hosted-pool",
|
|
31610
32027
|
refusal: null,
|
|
31611
32028
|
venue: () => hostedVenue(),
|
|
31612
|
-
imageFor: (runtime, override, version) => imageForRuntime(runtime, override, version)
|
|
32029
|
+
imageFor: (runtime, override, version, variant) => imageForRuntime(runtime, override, version, variant)
|
|
31613
32030
|
};
|
|
31614
32031
|
}
|
|
31615
32032
|
function placementFor(kind) {
|
|
@@ -32174,6 +32591,9 @@ function detectRuntime(repo) {
|
|
|
32174
32591
|
if (repo.listNames("").some((name) => /\.(?:csproj|fsproj|sln)$/.test(name))) {
|
|
32175
32592
|
candidates.push("dotnet");
|
|
32176
32593
|
}
|
|
32594
|
+
if (candidates.length === 0 && repo.listFiles("").some((f) => f.endsWith(".java"))) {
|
|
32595
|
+
candidates.push("jvm");
|
|
32596
|
+
}
|
|
32177
32597
|
return { runtime: candidates[0] ?? "unknown", candidates };
|
|
32178
32598
|
}
|
|
32179
32599
|
function readJsonObject(repo, path5) {
|
|
@@ -32321,6 +32741,11 @@ function basePythonInstallCommand(repo) {
|
|
|
32321
32741
|
}
|
|
32322
32742
|
return null;
|
|
32323
32743
|
}
|
|
32744
|
+
function rehearse(command) {
|
|
32745
|
+
const copy = '"$R/.terminalhire-rehearsal"';
|
|
32746
|
+
const home = '"$R/.terminalhire-rehearsal-home"';
|
|
32747
|
+
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; }`;
|
|
32748
|
+
}
|
|
32324
32749
|
function otherRuntimeCommands(repo, runtime) {
|
|
32325
32750
|
switch (runtime) {
|
|
32326
32751
|
case "go":
|
|
@@ -32348,10 +32773,21 @@ function otherRuntimeCommands(repo, runtime) {
|
|
|
32348
32773
|
case "dotnet":
|
|
32349
32774
|
return { install: "dotnet restore", test: "dotnet test" };
|
|
32350
32775
|
case "jvm": {
|
|
32351
|
-
if (repo.exists(
|
|
32352
|
-
return { install:
|
|
32776
|
+
if (!JVM_BUILD_FILES.some((file) => repo.exists(file)))
|
|
32777
|
+
return { install: null, test: null };
|
|
32778
|
+
if (repo.exists("pom.xml")) {
|
|
32779
|
+
return {
|
|
32780
|
+
install: `mvn -B dependency:go-offline && ${rehearse('mvn -B test -Dmaven.test.failure.ignore=true -Dmaven.repo.local="$R/.m2/repository"')}`,
|
|
32781
|
+
test: "mvn -B -o test"
|
|
32782
|
+
};
|
|
32783
|
+
}
|
|
32353
32784
|
const wrapper = repo.exists("gradlew") ? "./gradlew" : "gradle";
|
|
32354
|
-
return {
|
|
32785
|
+
return {
|
|
32786
|
+
install: `${wrapper} dependencies && ${rehearse(`${wrapper} test --continue`)}`,
|
|
32787
|
+
// `--no-build-cache`: the rehearsal above can fill Gradle's build cache, and a
|
|
32788
|
+
// test task restored FROM-CACHE runs nothing and prints no count.
|
|
32789
|
+
test: `${wrapper} test --offline --no-build-cache`
|
|
32790
|
+
};
|
|
32355
32791
|
}
|
|
32356
32792
|
default:
|
|
32357
32793
|
return { install: null, test: null };
|
|
@@ -32383,6 +32819,15 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
32383
32819
|
push(".ruby-version", repo.readText(".ruby-version"));
|
|
32384
32820
|
} else if (runtime === "dotnet") {
|
|
32385
32821
|
push("global.json sdk.version", readStringField(readObjectField(readJsonObject(repo, "global.json"), "sdk"), "version"));
|
|
32822
|
+
} else if (runtime === "jvm") {
|
|
32823
|
+
const pom = repo.readText("pom.xml");
|
|
32824
|
+
const gradle = repo.readText("build.gradle") ?? repo.readText("build.gradle.kts");
|
|
32825
|
+
push("build.gradle toolchain languageVersion", javaMajor(matchFirst(gradle, /JavaLanguageVersion\.of\(\s*["']?(\d+)["']?\s*\)/) ?? matchFirst(gradle, /jvmToolchain\(\s*(\d+)\s*\)/)));
|
|
32826
|
+
push(".java-version", javaMajor(repo.readText(".java-version")));
|
|
32827
|
+
push("pom.xml maven.compiler.release", javaMajor(matchFirst(pom, /<maven\.compiler\.release>\s*([^<\s]+)\s*</)));
|
|
32828
|
+
push("pom.xml java.version", javaMajor(matchFirst(pom, /<java\.version>\s*([^<\s]+)\s*</)));
|
|
32829
|
+
push("pom.xml maven.compiler.source", javaMajor(matchFirst(pom, /<maven\.compiler\.source>\s*([^<\s]+)\s*</)));
|
|
32830
|
+
push("build.gradle sourceCompatibility", javaMajor(matchFirst(gradle, /sourceCompatibility\s*=\s*JavaVersion\.VERSION_([\d_]+)/)?.replace("_", ".") ?? matchFirst(gradle, /sourceCompatibility\s*=\s*["']?([\d.]+)["']?/)));
|
|
32386
32831
|
}
|
|
32387
32832
|
let rangeFound = null;
|
|
32388
32833
|
for (const source of sources) {
|
|
@@ -32396,13 +32841,21 @@ function searchRuntimeVersion(repo, runtime) {
|
|
|
32396
32841
|
}
|
|
32397
32842
|
return { version: null, searched: sources.map((s) => s.label), rangeFound };
|
|
32398
32843
|
}
|
|
32844
|
+
function javaMajor(text) {
|
|
32845
|
+
if (text === null)
|
|
32846
|
+
return null;
|
|
32847
|
+
const match2 = /^(?:1\.(\d+)|(\d+))(?:[._][\d_.]*)?$/.exec(text.trim());
|
|
32848
|
+
if (match2 === null)
|
|
32849
|
+
return null;
|
|
32850
|
+
return match2[1] ?? match2[2] ?? null;
|
|
32851
|
+
}
|
|
32399
32852
|
function matchFirst(text, pattern) {
|
|
32400
32853
|
if (text === null)
|
|
32401
32854
|
return null;
|
|
32402
32855
|
const match2 = pattern.exec(text);
|
|
32403
32856
|
return match2 === null ? null : match2[1];
|
|
32404
32857
|
}
|
|
32405
|
-
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
32858
|
+
var RUNTIME_MANIFESTS, MANIFEST_FILENAMES, JVM_BUILD_FILES, NPM_PLACEHOLDER_TEST, REQUIREMENT_SPECIFIER, EXACT_VERSION;
|
|
32406
32859
|
var init_manifest2 = __esm({
|
|
32407
32860
|
"../../packages/envspec/dist/manifest.js"() {
|
|
32408
32861
|
"use strict";
|
|
@@ -32416,6 +32869,7 @@ var init_manifest2 = __esm({
|
|
|
32416
32869
|
{ runtime: "dotnet", files: [] }
|
|
32417
32870
|
];
|
|
32418
32871
|
MANIFEST_FILENAMES = RUNTIME_MANIFESTS.flatMap((m) => m.files).concat(["*.csproj", "*.fsproj", "*.sln"]).sort();
|
|
32872
|
+
JVM_BUILD_FILES = ["build.gradle", "build.gradle.kts", "pom.xml"];
|
|
32419
32873
|
NPM_PLACEHOLDER_TEST = /^echo\s+["']?Error:\s*no test specified["']?\s*&&\s*exit\s+1$/;
|
|
32420
32874
|
REQUIREMENT_SPECIFIER = /^[A-Za-z0-9._-]+(\[[A-Za-z0-9._,-]+\])?([<>=!~]=?[A-Za-z0-9._*+-]+(,[<>=!~]=?[A-Za-z0-9._*+-]+)*)?$/;
|
|
32421
32875
|
EXACT_VERSION = /^v?(\d+(?:\.\d+){0,2})$/;
|
|
@@ -32812,7 +33266,7 @@ function deriveFromReader(repo) {
|
|
|
32812
33266
|
searched: MANIFEST_FILENAMES,
|
|
32813
33267
|
detail: `no ecosystem manifest was found at the repo root (looked for ${MANIFEST_FILENAMES.join(", ")}), so the language runtime could not be identified`
|
|
32814
33268
|
});
|
|
32815
|
-
} else {
|
|
33269
|
+
} else if (runtime !== "jvm" || JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
32816
33270
|
derivedFrom.add("manifest");
|
|
32817
33271
|
}
|
|
32818
33272
|
if (detection.candidates.length > 1) {
|
|
@@ -32976,12 +33430,13 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
32976
33430
|
const setup = SETUP_ACTIONS[runtime];
|
|
32977
33431
|
const searched = [];
|
|
32978
33432
|
let rangeFound = null;
|
|
33433
|
+
const pin = (raw) => runtime === "jvm" ? javaMajor(raw) : exactVersion(raw);
|
|
32979
33434
|
if (job !== null && setup !== void 0) {
|
|
32980
33435
|
const direct = findActionInput(job, setup.action, setup.input);
|
|
32981
33436
|
if (direct !== null) {
|
|
32982
33437
|
searched.push(`${job.file} ${setup.action} ${setup.input}`);
|
|
32983
33438
|
const reduced = reduceExpression(direct.command, job.singletons);
|
|
32984
|
-
const exact =
|
|
33439
|
+
const exact = pin(reduced);
|
|
32985
33440
|
if (exact !== null)
|
|
32986
33441
|
return { value: exact, searched, rangeFound: null };
|
|
32987
33442
|
if (reduced !== null)
|
|
@@ -32990,7 +33445,7 @@ function deriveRuntimeVersion(repo, runtime, job) {
|
|
|
32990
33445
|
const viaFile = findActionInput(job, setup.action, setup.fileInput);
|
|
32991
33446
|
if (viaFile !== null) {
|
|
32992
33447
|
searched.push(`${job.file} ${setup.action} ${setup.fileInput} -> ${viaFile.command}`);
|
|
32993
|
-
const exact =
|
|
33448
|
+
const exact = pin(repo.readText(viaFile.command));
|
|
32994
33449
|
if (exact !== null)
|
|
32995
33450
|
return { value: exact, searched, rangeFound: null };
|
|
32996
33451
|
}
|
|
@@ -33015,6 +33470,8 @@ function testSearchPaths(runtime, workflowFiles) {
|
|
|
33015
33470
|
paths.push("**/*_test.go");
|
|
33016
33471
|
if (runtime === "ruby")
|
|
33017
33472
|
paths.push("Gemfile", "Rakefile");
|
|
33473
|
+
if (runtime === "jvm")
|
|
33474
|
+
paths.push(...JVM_BUILD_FILES);
|
|
33018
33475
|
if (runtime === "unknown")
|
|
33019
33476
|
paths.push(...MANIFEST_FILENAMES);
|
|
33020
33477
|
return [...new Set(paths)].sort();
|
|
@@ -33032,6 +33489,9 @@ function describeTestSearch(repo, runtime, workflowFiles) {
|
|
|
33032
33489
|
if (runtime === "python") {
|
|
33033
33490
|
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`;
|
|
33034
33491
|
}
|
|
33492
|
+
if (runtime === "jvm" && !JVM_BUILD_FILES.some((file) => repo.exists(file))) {
|
|
33493
|
+
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`;
|
|
33494
|
+
}
|
|
33035
33495
|
return `${ciPart}, and no ${runtime} test convention applies to this tree`;
|
|
33036
33496
|
}
|
|
33037
33497
|
function installSearchPaths(runtime, workflowFiles) {
|
|
@@ -33040,6 +33500,8 @@ function installSearchPaths(runtime, workflowFiles) {
|
|
|
33040
33500
|
paths.push("package-lock.json", "pnpm-lock.yaml", "yarn.lock");
|
|
33041
33501
|
if (runtime === "python")
|
|
33042
33502
|
paths.push("poetry.lock", "pyproject.toml", "requirements.txt", "uv.lock");
|
|
33503
|
+
if (runtime === "jvm")
|
|
33504
|
+
paths.push(...JVM_BUILD_FILES);
|
|
33043
33505
|
if (runtime === "unknown")
|
|
33044
33506
|
paths.push(...MANIFEST_FILENAMES);
|
|
33045
33507
|
return [...new Set(paths)].sort();
|
|
@@ -33118,12 +33580,41 @@ var init_dist3 = __esm({
|
|
|
33118
33580
|
}
|
|
33119
33581
|
});
|
|
33120
33582
|
|
|
33583
|
+
// ../../packages/envrun/dist/gradleTestSummary.js
|
|
33584
|
+
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync14 } from "fs";
|
|
33585
|
+
import { join as join26 } from "path";
|
|
33586
|
+
function stageGradleTestSummary(jailHome) {
|
|
33587
|
+
const dir = join26(jailHome, ".gradle", "init.d");
|
|
33588
|
+
mkdirSync5(dir, { recursive: true });
|
|
33589
|
+
writeFileSync14(join26(dir, "terminalhire-test-summary.gradle"), GRADLE_TEST_SUMMARY_INIT);
|
|
33590
|
+
}
|
|
33591
|
+
var GRADLE_TEST_MARKER, GRADLE_TEST_SUMMARY_INIT;
|
|
33592
|
+
var init_gradleTestSummary = __esm({
|
|
33593
|
+
"../../packages/envrun/dist/gradleTestSummary.js"() {
|
|
33594
|
+
"use strict";
|
|
33595
|
+
GRADLE_TEST_MARKER = "terminalhire-gradle-tests:";
|
|
33596
|
+
GRADLE_TEST_SUMMARY_INIT = `// Written by terminalhire (TERM-1122): prints each Test task's counts, because
|
|
33597
|
+
// Gradle prints none when every test passes.
|
|
33598
|
+
allprojects {
|
|
33599
|
+
tasks.withType(Test).configureEach { task ->
|
|
33600
|
+
def label = task.path
|
|
33601
|
+
task.afterSuite { desc, result ->
|
|
33602
|
+
if (desc.parent == null) {
|
|
33603
|
+
println "${GRADLE_TEST_MARKER} task=\${label} total=\${result.testCount} passed=\${result.successfulTestCount} failed=\${result.failedTestCount} skipped=\${result.skippedTestCount}"
|
|
33604
|
+
}
|
|
33605
|
+
}
|
|
33606
|
+
}
|
|
33607
|
+
}
|
|
33608
|
+
`;
|
|
33609
|
+
}
|
|
33610
|
+
});
|
|
33611
|
+
|
|
33121
33612
|
// ../../packages/envrun/dist/thrun.js
|
|
33122
33613
|
import { execFileSync, spawnSync as spawnSync6 } from "child_process";
|
|
33123
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
33614
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, mkdtempSync as mkdtempSync4, rmSync as rmSync9 } from "fs";
|
|
33124
33615
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
33125
33616
|
import { tmpdir as tmpdir4 } from "os";
|
|
33126
|
-
import { join as
|
|
33617
|
+
import { join as join27 } from "path";
|
|
33127
33618
|
function git(repoDir, args, allowNonZero = false) {
|
|
33128
33619
|
const res = spawnSync6("git", [...args], {
|
|
33129
33620
|
cwd: repoDir,
|
|
@@ -33138,7 +33629,7 @@ function git(repoDir, args, allowNonZero = false) {
|
|
|
33138
33629
|
return res.stdout ?? "";
|
|
33139
33630
|
}
|
|
33140
33631
|
function collectWorkingDiff(repoDir, opts = {}) {
|
|
33141
|
-
if (!existsSync12(
|
|
33632
|
+
if (!existsSync12(join27(repoDir, ".git"))) {
|
|
33142
33633
|
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.`);
|
|
33143
33634
|
}
|
|
33144
33635
|
const headSha = git(repoDir, ["rev-parse", "HEAD"]).trim();
|
|
@@ -33286,7 +33777,7 @@ function credentialFreeHome() {
|
|
|
33286
33777
|
return credentialFreeHomeDir;
|
|
33287
33778
|
let made;
|
|
33288
33779
|
try {
|
|
33289
|
-
made = mkdtempSync4(
|
|
33780
|
+
made = mkdtempSync4(join27(tmpdir4(), "th-run-nohome-"));
|
|
33290
33781
|
} catch (err) {
|
|
33291
33782
|
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 });
|
|
33292
33783
|
}
|
|
@@ -33361,7 +33852,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
33361
33852
|
if (persisted !== null) {
|
|
33362
33853
|
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.`);
|
|
33363
33854
|
}
|
|
33364
|
-
|
|
33855
|
+
mkdirSync6(opts.dest, { recursive: true });
|
|
33365
33856
|
const runOut = (args) => execFileSync("git", [...gitConfigArgs(), ...args], {
|
|
33366
33857
|
cwd: opts.dest,
|
|
33367
33858
|
encoding: "utf8",
|
|
@@ -33400,7 +33891,7 @@ function cloneTargetAtUnguarded(opts) {
|
|
|
33400
33891
|
}
|
|
33401
33892
|
function scrubCloneSource(dest, run2) {
|
|
33402
33893
|
run2(["remote", "remove", "origin"]);
|
|
33403
|
-
rmSync9(
|
|
33894
|
+
rmSync9(join27(dest, ".git", "FETCH_HEAD"), { force: true });
|
|
33404
33895
|
}
|
|
33405
33896
|
function publishableTarget(url) {
|
|
33406
33897
|
if (separatorInTarget(url) !== null)
|
|
@@ -33539,12 +34030,18 @@ function refusedRun(fields) {
|
|
|
33539
34030
|
treeDigest: null,
|
|
33540
34031
|
baselinePatchSha256: null,
|
|
33541
34032
|
testCommandSource: "none",
|
|
34033
|
+
// Nothing was booted, so nobody chose an image. Same reasoning as `containerImage: null`
|
|
34034
|
+
// below: it must not read as an image we picked and cannot name.
|
|
34035
|
+
imageSource: "none",
|
|
33542
34036
|
boundaryRefusals: fields.boundaryRefusals,
|
|
33543
34037
|
touchedPaths: fields.touchedPaths,
|
|
33544
34038
|
preview: null,
|
|
33545
34039
|
containerImage: null,
|
|
33546
34040
|
containerImageDigest: null,
|
|
33547
34041
|
leaksClean: null,
|
|
34042
|
+
// Null for the same reason, and never `unobserved`: that word says we tried to take a
|
|
34043
|
+
// census and could not, and here there was nothing to take one of (TERM-1144).
|
|
34044
|
+
leakState: null,
|
|
33548
34045
|
// A refused run never held a lease, so there is no venue to describe. Same
|
|
33549
34046
|
// reasoning as `leaksClean` above: null because nothing happened, and it must
|
|
33550
34047
|
// not read as a venue we looked at and could not name.
|
|
@@ -33772,10 +34269,10 @@ async function runVerification(req, ctx) {
|
|
|
33772
34269
|
venueIdentity: null
|
|
33773
34270
|
};
|
|
33774
34271
|
}
|
|
33775
|
-
const stage =
|
|
33776
|
-
const cloneDir =
|
|
33777
|
-
const scratch =
|
|
33778
|
-
|
|
34272
|
+
const stage = join27(req.scratchRoot, runId);
|
|
34273
|
+
const cloneDir = join27(stage, "clone");
|
|
34274
|
+
const scratch = join27(stage, "scratch");
|
|
34275
|
+
mkdirSync6(scratch, { recursive: true });
|
|
33779
34276
|
assertSafeTargetSha(req.targetSha);
|
|
33780
34277
|
progress("clone", `${publishableTarget(req.targetRepo)} @ ${req.targetSha.slice(0, 12)}`);
|
|
33781
34278
|
cloneTargetAt({
|
|
@@ -33802,7 +34299,8 @@ async function runVerification(req, ctx) {
|
|
|
33802
34299
|
const derived = deriveEnvironmentSpec(cloneDir);
|
|
33803
34300
|
const spec = req.testCommandOverride === void 0 ? derived : { ...derived, testCommand: req.testCommandOverride };
|
|
33804
34301
|
progress("derive", `runtime=${spec.runtime} install=${String(spec.installCommand)} test=${String(spec.testCommand)}`);
|
|
33805
|
-
|
|
34302
|
+
refuseUnbuildableSpec(spec);
|
|
34303
|
+
const image = placement.imageFor(spec.runtime, req.image, spec.runtimeVersion, imageVariantFor(spec));
|
|
33806
34304
|
const resolved = await resolveLease(placement, runId);
|
|
33807
34305
|
if (!resolved.ok) {
|
|
33808
34306
|
return {
|
|
@@ -33837,10 +34335,12 @@ async function runVerification(req, ctx) {
|
|
|
33837
34335
|
const lease = resolved.lease;
|
|
33838
34336
|
try {
|
|
33839
34337
|
buildJail(scratch);
|
|
34338
|
+
if (spec.runtime === "jvm")
|
|
34339
|
+
stageGradleTestSummary(localJailPaths(scratch).jail);
|
|
33840
34340
|
const venuePaths = await lease.stage({
|
|
33841
34341
|
cloneDir,
|
|
33842
34342
|
scratchRoot: scratch,
|
|
33843
|
-
previewDir:
|
|
34343
|
+
previewDir: join27(stage, "preview"),
|
|
33844
34344
|
// On a dispatched run the commit is the statement of what was tested, so
|
|
33845
34345
|
// it rides with the tree and the venue seam refuses a tree that is not
|
|
33846
34346
|
// that commit (design §6 item 4, TERM-892 — the guard lives in
|
|
@@ -33887,7 +34387,7 @@ async function runVerification(req, ctx) {
|
|
|
33887
34387
|
// that `founder-declared` (as this did for one review round) signs the counterparty's
|
|
33888
34388
|
// name onto the developer's choice, which is worse than laundering it as `detected`:
|
|
33889
34389
|
// it is a specific false attribution inside a field a reviewer trusts.
|
|
33890
|
-
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
34390
|
+
testCommandSource: req.testCommandOverride !== void 0 ? req.testCommandOverrideOrigin === "founder" ? "founder-declared" : req.testCommandOverrideOrigin === "operator" ? "operator-declared" : "developer-declared" : derived.testCommand === null ? "none" : "detected",
|
|
33891
34391
|
boundaryRefusals: [],
|
|
33892
34392
|
touchedPaths: pre.touchedPaths,
|
|
33893
34393
|
preview: null,
|
|
@@ -33897,7 +34397,14 @@ async function runVerification(req, ctx) {
|
|
|
33897
34397
|
// that measures one; a run without it is recordable but not attestable —
|
|
33898
34398
|
// `toAcceptancePredicate` refuses `missing-image-digest` (TERM-893).
|
|
33899
34399
|
containerImageDigest: null,
|
|
34400
|
+
// The image half of the provenance pair above. `detected` means the runtime mapping
|
|
34401
|
+
// chose the environment; an override names the human. Defaulting an unstated origin to
|
|
34402
|
+
// `developer-declared` is deliberate and matches `testCommandSource`: `th run --image`
|
|
34403
|
+
// runs on the developer's machine, judging the developer's work, so attributing it to
|
|
34404
|
+
// the operator would sign our name onto their choice.
|
|
34405
|
+
imageSource: req.image === void 0 ? "detected" : req.imageOrigin === "operator" ? "operator-declared" : "developer-declared",
|
|
33900
34406
|
leaksClean: verdict.leaks.clean,
|
|
34407
|
+
leakState: verdict.leaks.state,
|
|
33901
34408
|
// Built from the LEASE, over the client that ran the steps — never from
|
|
33902
34409
|
// `req.placement`, which is a request. `venueDescriptor.ts` carries the
|
|
33903
34410
|
// reasoning and the #735 failure that makes the distinction load-bearing.
|
|
@@ -33955,6 +34462,7 @@ var init_thrun = __esm({
|
|
|
33955
34462
|
init_execute();
|
|
33956
34463
|
init_placement();
|
|
33957
34464
|
init_venue();
|
|
34465
|
+
init_gradleTestSummary();
|
|
33958
34466
|
init_venueDescriptor();
|
|
33959
34467
|
init_result();
|
|
33960
34468
|
ThRunError = class extends Error {
|
|
@@ -34198,7 +34706,7 @@ var init_dbplan = __esm({
|
|
|
34198
34706
|
// ../../packages/envrun/dist/dbstack.js
|
|
34199
34707
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
34200
34708
|
import { randomBytes as randomBytes11 } from "crypto";
|
|
34201
|
-
import { mkdirSync as
|
|
34709
|
+
import { mkdirSync as mkdirSync7 } from "fs";
|
|
34202
34710
|
function installCommandFor(runner) {
|
|
34203
34711
|
switch (runner) {
|
|
34204
34712
|
case "sql":
|
|
@@ -34429,7 +34937,7 @@ function startDatabase(req) {
|
|
|
34429
34937
|
if (!ready.ok) {
|
|
34430
34938
|
throw new DbStackError(`INFRASTRUCTURE/INCONCLUSIVE: Postgres never accepted queries at 127.0.0.1:${String(creds.port)} within the readiness window: ${ready.detail}`);
|
|
34431
34939
|
}
|
|
34432
|
-
const
|
|
34940
|
+
const query2 = (sql) => {
|
|
34433
34941
|
const res = docker2([
|
|
34434
34942
|
"exec",
|
|
34435
34943
|
`--env=PGPASSWORD=${creds.password}`,
|
|
@@ -34477,7 +34985,7 @@ function startDatabase(req) {
|
|
|
34477
34985
|
credentials: creds,
|
|
34478
34986
|
image,
|
|
34479
34987
|
readyMs: ready.ms,
|
|
34480
|
-
query,
|
|
34988
|
+
query: query2,
|
|
34481
34989
|
runOnNetwork,
|
|
34482
34990
|
teardown
|
|
34483
34991
|
};
|
|
@@ -34540,8 +35048,8 @@ async function installLocalMigrationTooling(opts) {
|
|
|
34540
35048
|
};
|
|
34541
35049
|
}
|
|
34542
35050
|
const { jail, tmp } = buildJail(opts.scratchRoot);
|
|
34543
|
-
|
|
34544
|
-
|
|
35051
|
+
mkdirSync7(jail, { recursive: true });
|
|
35052
|
+
mkdirSync7(tmp, { recursive: true });
|
|
34545
35053
|
const spec = {
|
|
34546
35054
|
profile: "install",
|
|
34547
35055
|
clone: opts.repoDir,
|
|
@@ -34836,6 +35344,7 @@ __export(dist_exports, {
|
|
|
34836
35344
|
GOOGLE_JWKS_URL: () => GOOGLE_JWKS_URL,
|
|
34837
35345
|
HostedVenueError: () => HostedVenueError,
|
|
34838
35346
|
JWKS_FETCH_TIMEOUT_MS: () => JWKS_FETCH_TIMEOUT_MS,
|
|
35347
|
+
LEAK_STATES: () => LEAK_STATES,
|
|
34839
35348
|
LOCAL_MEASUREMENT_PREFIX: () => LOCAL_MEASUREMENT_PREFIX,
|
|
34840
35349
|
LabelWatch: () => LabelWatch,
|
|
34841
35350
|
MIN_GIT_VERSION_FOR_END_OF_OPTIONS: () => MIN_GIT_VERSION_FOR_END_OF_OPTIONS,
|
|
@@ -34852,6 +35361,7 @@ __export(dist_exports, {
|
|
|
34852
35361
|
REDACTED_TARGET_SHA: () => REDACTED_TARGET_SHA,
|
|
34853
35362
|
RELEASED_LEASE_CENSUS_REASON: () => RELEASED_LEASE_CENSUS_REASON,
|
|
34854
35363
|
REPO_DIGEST_RE: () => REPO_DIGEST_RE,
|
|
35364
|
+
RUN_IMAGE_SOURCES: () => RUN_IMAGE_SOURCES,
|
|
34855
35365
|
RUN_LABEL_KEY: () => RUN_LABEL_KEY,
|
|
34856
35366
|
RUN_RESULT_FIELDS: () => RUN_RESULT_FIELDS,
|
|
34857
35367
|
RUN_RESULT_SCHEMA: () => RUN_RESULT_SCHEMA,
|
|
@@ -34868,6 +35378,7 @@ __export(dist_exports, {
|
|
|
34868
35378
|
VENUE_GCLOUD_CONFIG: () => VENUE_GCLOUD_CONFIG,
|
|
34869
35379
|
VENUE_SSH_USER: () => VENUE_SSH_USER,
|
|
34870
35380
|
VENV_DIR: () => VENV_DIR,
|
|
35381
|
+
VERIFICATION_OUTCOMES: () => VERIFICATION_OUTCOMES,
|
|
34871
35382
|
VenueRollbackError: () => VenueRollbackError,
|
|
34872
35383
|
acquireTransactionally: () => acquireTransactionally,
|
|
34873
35384
|
alembicChainPosition: () => alembicChainPosition,
|
|
@@ -34881,6 +35392,7 @@ __export(dist_exports, {
|
|
|
34881
35392
|
assertVenueOwnerDeclared: () => assertVenueOwnerDeclared,
|
|
34882
35393
|
bookkeepingFor: () => bookkeepingFor,
|
|
34883
35394
|
census: () => census,
|
|
35395
|
+
censusReport: () => censusReport,
|
|
34884
35396
|
censusTotal: () => censusTotal,
|
|
34885
35397
|
classifyBootFailure: () => classifyBootFailure,
|
|
34886
35398
|
classifyProbeFailure: () => classifyProbeFailure,
|
|
@@ -34900,6 +35412,7 @@ __export(dist_exports, {
|
|
|
34900
35412
|
detectRunner: () => detectRunner,
|
|
34901
35413
|
endOfOptionsUnsupported: () => endOfOptionsUnsupported,
|
|
34902
35414
|
ensureVenueServiceCredentials: () => ensureVenueServiceCredentials,
|
|
35415
|
+
exitCodeFor: () => exitCodeFor,
|
|
34903
35416
|
failureSourceOf: () => failureSourceOf,
|
|
34904
35417
|
findRunRefusal: () => findRunRefusal,
|
|
34905
35418
|
gcpBootArgv: () => gcpBootArgv,
|
|
@@ -34914,6 +35427,7 @@ __export(dist_exports, {
|
|
|
34914
35427
|
identityProbeCommand: () => identityProbeCommand,
|
|
34915
35428
|
imageForRuntime: () => imageForRuntime,
|
|
34916
35429
|
imageRepo: () => imageRepo,
|
|
35430
|
+
imageVariantFor: () => imageVariantFor,
|
|
34917
35431
|
installCommandFor: () => installCommandFor,
|
|
34918
35432
|
installLocalMigrationTooling: () => installLocalMigrationTooling,
|
|
34919
35433
|
isBookkeepingTable: () => isBookkeepingTable,
|
|
@@ -34943,6 +35457,7 @@ __export(dist_exports, {
|
|
|
34943
35457
|
readSchema: () => readSchema,
|
|
34944
35458
|
recordedApplied: () => recordedApplied,
|
|
34945
35459
|
refuseSshTransport: () => refuseSshTransport,
|
|
35460
|
+
refuseUnbuildableSpec: () => refuseUnbuildableSpec,
|
|
34946
35461
|
renderRunReport: () => renderRunReport,
|
|
34947
35462
|
renderVenueLine: () => renderVenueLine,
|
|
34948
35463
|
renderVerdictLine: () => renderVerdictLine,
|
|
@@ -35029,8 +35544,8 @@ __export(cache_store_exports, {
|
|
|
35029
35544
|
updateIndexCache: () => updateIndexCache,
|
|
35030
35545
|
writeIndexCache: () => writeIndexCache
|
|
35031
35546
|
});
|
|
35032
|
-
import { readFileSync as readFileSync13, writeFileSync as
|
|
35033
|
-
import { join as
|
|
35547
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync15, renameSync as renameSync5 } from "fs";
|
|
35548
|
+
import { join as join28 } from "path";
|
|
35034
35549
|
import { homedir as homedir13 } from "os";
|
|
35035
35550
|
function readCacheEntry() {
|
|
35036
35551
|
try {
|
|
@@ -35049,7 +35564,7 @@ function updateIndexCache(patch) {
|
|
|
35049
35564
|
ts: Date.now()
|
|
35050
35565
|
};
|
|
35051
35566
|
const tmp = `${INDEX_CACHE_FILE}.${process.pid}.${tmpCounter++}.tmp`;
|
|
35052
|
-
|
|
35567
|
+
writeFileSync15(tmp, JSON.stringify(entry), "utf8");
|
|
35053
35568
|
renameSync5(tmp, INDEX_CACHE_FILE);
|
|
35054
35569
|
return entry;
|
|
35055
35570
|
}
|
|
@@ -35061,8 +35576,8 @@ var init_cache_store = __esm({
|
|
|
35061
35576
|
"bin/cache-store.js"() {
|
|
35062
35577
|
"use strict";
|
|
35063
35578
|
init_state_dir();
|
|
35064
|
-
TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR ||
|
|
35065
|
-
INDEX_CACHE_FILE =
|
|
35579
|
+
TERMINALHIRE_DIR10 = process.env.TERMINALHIRE_DIR || join28(homedir13(), ".terminalhire");
|
|
35580
|
+
INDEX_CACHE_FILE = join28(TERMINALHIRE_DIR10, "index-cache.json");
|
|
35066
35581
|
SCHEMA_VERSION2 = 1;
|
|
35067
35582
|
tmpCounter = 0;
|
|
35068
35583
|
}
|
|
@@ -35262,8 +35777,8 @@ var init_audit2 = __esm({
|
|
|
35262
35777
|
init_src();
|
|
35263
35778
|
import {
|
|
35264
35779
|
readFileSync as readFileSync14,
|
|
35265
|
-
writeFileSync as
|
|
35266
|
-
mkdirSync as
|
|
35780
|
+
writeFileSync as writeFileSync16,
|
|
35781
|
+
mkdirSync as mkdirSync8,
|
|
35267
35782
|
mkdtempSync as mkdtempSync5,
|
|
35268
35783
|
renameSync as renameSync6,
|
|
35269
35784
|
existsSync as existsSync13,
|
|
@@ -35272,7 +35787,7 @@ import {
|
|
|
35272
35787
|
rmSync as rmSync10,
|
|
35273
35788
|
readdirSync as readdirSync3
|
|
35274
35789
|
} from "fs";
|
|
35275
|
-
import { join as
|
|
35790
|
+
import { join as join29, dirname as dirname8, isAbsolute as isAbsolute4, resolve as pathResolve } from "path";
|
|
35276
35791
|
import { createHash as createHash10 } from "crypto";
|
|
35277
35792
|
import { homedir as homedir14, hostname as osHostname } from "os";
|
|
35278
35793
|
import { execFile as execFile3, execFileSync as execFileSync2, spawnSync as spawnSync8 } from "child_process";
|
|
@@ -35719,10 +36234,10 @@ async function syncFounderVerdicts({
|
|
|
35719
36234
|
|
|
35720
36235
|
// bin/jpi-claim.js
|
|
35721
36236
|
init_founder_note_sync();
|
|
35722
|
-
var TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR ||
|
|
35723
|
-
var INDEX_CACHE_FILE2 =
|
|
35724
|
-
var CLAIM_PUSH_MARKER =
|
|
35725
|
-
var REPO_CONTINUITY_NUDGE_MARKER =
|
|
36237
|
+
var TERMINALHIRE_DIR11 = process.env.TERMINALHIRE_DIR || join29(homedir14(), ".terminalhire");
|
|
36238
|
+
var INDEX_CACHE_FILE2 = join29(TERMINALHIRE_DIR11, "index-cache.json");
|
|
36239
|
+
var CLAIM_PUSH_MARKER = join29(TERMINALHIRE_DIR11, "claim-push.json");
|
|
36240
|
+
var REPO_CONTINUITY_NUDGE_MARKER = join29(TERMINALHIRE_DIR11, "repo-continuity-nudged.json");
|
|
35726
36241
|
function readNudgedClaimIds() {
|
|
35727
36242
|
try {
|
|
35728
36243
|
const raw = JSON.parse(readFileSync14(REPO_CONTINUITY_NUDGE_MARKER, "utf8"));
|
|
@@ -35736,7 +36251,7 @@ function markClaimNudged(id) {
|
|
|
35736
36251
|
const ids2 = readNudgedClaimIds();
|
|
35737
36252
|
ids2.add(id);
|
|
35738
36253
|
ensureStateDir(TERMINALHIRE_DIR11);
|
|
35739
|
-
|
|
36254
|
+
writeFileSync16(REPO_CONTINUITY_NUDGE_MARKER, JSON.stringify({ claimIds: [...ids2] }), "utf8");
|
|
35740
36255
|
} catch {
|
|
35741
36256
|
}
|
|
35742
36257
|
}
|
|
@@ -38069,7 +38584,7 @@ async function cmdAttach(id, worktree, branch) {
|
|
|
38069
38584
|
function workDirFor(repoFullName, issueNumber) {
|
|
38070
38585
|
const [owner, repo] = String(repoFullName).split("/");
|
|
38071
38586
|
const suffix = issueNumber ? `-${issueNumber}` : "";
|
|
38072
|
-
return
|
|
38587
|
+
return join29(homedir14(), "terminalhire", "work", `${owner}-${repo}${suffix}`);
|
|
38073
38588
|
}
|
|
38074
38589
|
function startBranchFor(repoFullName, issueNumber) {
|
|
38075
38590
|
const repo = String(repoFullName).split("/")[1] || "claim";
|
|
@@ -38325,7 +38840,7 @@ terminalhire claim: not started \u2014 starting forks ${claim.repoFullName} to y
|
|
|
38325
38840
|
);
|
|
38326
38841
|
process.exit(1);
|
|
38327
38842
|
}
|
|
38328
|
-
|
|
38843
|
+
mkdirSync8(join29(homedir14(), "terminalhire", "work"), { recursive: true });
|
|
38329
38844
|
const { createProgress: createProgress2, parseGitProgress: parseGitProgress2, splitProgressChunk: splitProgressChunk2, shStream: shStream2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
|
|
38330
38845
|
const progress = createProgress2();
|
|
38331
38846
|
let forkFullName;
|
|
@@ -38453,7 +38968,7 @@ function founderPostingIdOf(claim) {
|
|
|
38453
38968
|
}
|
|
38454
38969
|
function sliceWorkDirFor(claimLocalId) {
|
|
38455
38970
|
const safe = String(claimLocalId).replace(/[^A-Za-z0-9._-]/g, "-");
|
|
38456
|
-
return
|
|
38971
|
+
return join29(homedir14(), "terminalhire", "work", `slice-${safe}`);
|
|
38457
38972
|
}
|
|
38458
38973
|
function assertNoBooleanPath(dest, flagName) {
|
|
38459
38974
|
const last = String(dest).split(/[\\/]/).filter(Boolean).pop();
|
|
@@ -38578,9 +39093,9 @@ function writeSliceFiles(destDir, files) {
|
|
|
38578
39093
|
const unavailable = [];
|
|
38579
39094
|
for (const f of files) {
|
|
38580
39095
|
if (typeof f.content === "string") {
|
|
38581
|
-
const abs =
|
|
38582
|
-
|
|
38583
|
-
|
|
39096
|
+
const abs = join29(destDir, f.path);
|
|
39097
|
+
mkdirSync8(dirname8(abs), { recursive: true });
|
|
39098
|
+
writeFileSync16(abs, f.content, "utf8");
|
|
38584
39099
|
written.push(f.path);
|
|
38585
39100
|
} else {
|
|
38586
39101
|
unavailable.push({ path: f.path, reason: f.unavailableReason || "(no reason given)" });
|
|
@@ -38614,7 +39129,7 @@ function writeDeliveredBrief(destDir, spec) {
|
|
|
38614
39129
|
function ensureExcludedPackDir(destDir) {
|
|
38615
39130
|
let occupant = null;
|
|
38616
39131
|
try {
|
|
38617
|
-
occupant = lstatSync3(
|
|
39132
|
+
occupant = lstatSync3(join29(destDir, BRIEF_DIR));
|
|
38618
39133
|
} catch (err) {
|
|
38619
39134
|
if (err?.code !== "ENOENT") {
|
|
38620
39135
|
return {
|
|
@@ -38629,12 +39144,12 @@ function ensureExcludedPackDir(destDir) {
|
|
|
38629
39144
|
reason: `${BRIEF_DIR}/ already exists in the delivered tree, and excluding it would hide that content from your patch`
|
|
38630
39145
|
};
|
|
38631
39146
|
}
|
|
38632
|
-
const excludeFile =
|
|
39147
|
+
const excludeFile = join29(destDir, ".git", "info", "exclude");
|
|
38633
39148
|
try {
|
|
38634
39149
|
const existing = existsSync13(excludeFile) ? readFileSync14(excludeFile, "utf8") : "";
|
|
38635
39150
|
if (!existing.split("\n").includes(BRIEF_EXCLUDE_LINE)) {
|
|
38636
|
-
|
|
38637
|
-
|
|
39151
|
+
mkdirSync8(dirname8(excludeFile), { recursive: true });
|
|
39152
|
+
writeFileSync16(
|
|
38638
39153
|
excludeFile,
|
|
38639
39154
|
`${existing}${existing === "" || existing.endsWith("\n") ? "" : "\n"}${BRIEF_EXCLUDE_LINE}
|
|
38640
39155
|
`,
|
|
@@ -38648,9 +39163,9 @@ function ensureExcludedPackDir(destDir) {
|
|
|
38648
39163
|
}
|
|
38649
39164
|
function writePackFile(destDir, relPath, content, what) {
|
|
38650
39165
|
try {
|
|
38651
|
-
const abs =
|
|
38652
|
-
|
|
38653
|
-
|
|
39166
|
+
const abs = join29(destDir, relPath);
|
|
39167
|
+
mkdirSync8(dirname8(abs), { recursive: true });
|
|
39168
|
+
writeFileSync16(abs, content, { encoding: "utf8", flag: "wx" });
|
|
38654
39169
|
} catch (err) {
|
|
38655
39170
|
return { written: false, reason: `the ${what} could not be written (${err.message})` };
|
|
38656
39171
|
}
|
|
@@ -39065,7 +39580,7 @@ async function cmdSliceFullTier(claims, id, local, fullTierBody, flags, cloneRep
|
|
|
39065
39580
|
if (resolvedDir.suffixed) {
|
|
39066
39581
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${dest}`);
|
|
39067
39582
|
}
|
|
39068
|
-
|
|
39583
|
+
mkdirSync8(dest, { recursive: true });
|
|
39069
39584
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
39070
39585
|
let engine;
|
|
39071
39586
|
try {
|
|
@@ -39247,7 +39762,7 @@ async function attemptSliceDelivery(id, flags = {}) {
|
|
|
39247
39762
|
if (resolvedDir.suffixed) {
|
|
39248
39763
|
console.log(`terminalhire claim: the usual directory has content \u2014 using ${finalDest}`);
|
|
39249
39764
|
}
|
|
39250
|
-
|
|
39765
|
+
mkdirSync8(dirname8(finalDest), { recursive: true });
|
|
39251
39766
|
let dest = mkdtempSync5(`${finalDest}.tmp-`);
|
|
39252
39767
|
const { written, unavailable } = writeSliceFiles(dest, body.files);
|
|
39253
39768
|
const branch = `claim/${String(claim.id).replace(/[^A-Za-z0-9._-]/g, "-")}`;
|
|
@@ -39788,7 +40303,7 @@ async function cmdSubmit(id, flags = {}) {
|
|
|
39788
40303
|
const head = `${ghUser}:${claim.branch}`;
|
|
39789
40304
|
const title = flags.title || claim.title;
|
|
39790
40305
|
const noBody = Boolean(flags["no-body"]);
|
|
39791
|
-
const prBodyPath =
|
|
40306
|
+
const prBodyPath = join29(wt, "PR-BODY.md");
|
|
39792
40307
|
const bodySource = pickBodySource({
|
|
39793
40308
|
bodyFileFlag: flags["body-file"],
|
|
39794
40309
|
noBody,
|
|
@@ -40028,7 +40543,7 @@ function readClaimPushMarker() {
|
|
|
40028
40543
|
}
|
|
40029
40544
|
function writeClaimPushMarker(marker) {
|
|
40030
40545
|
ensureStateDir(TERMINALHIRE_DIR11);
|
|
40031
|
-
|
|
40546
|
+
writeFileSync16(CLAIM_PUSH_MARKER, JSON.stringify(marker, null, 2) + "\n", "utf8");
|
|
40032
40547
|
}
|
|
40033
40548
|
function clearClaimPushMarker() {
|
|
40034
40549
|
try {
|