@gjermundgaraba/upup 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as reason, t as openFlags } from "./io-BGJ4Yp7u.mjs";
2
+ import { n as openFlags, r as reason, t as byName } from "./io-ns6xhFdF.mjs";
3
3
  import { findPackageJSON } from "node:module";
4
4
  import { NodeRuntime, NodeServices, NodeStdio } from "@effect/platform-node";
5
5
  import { Cause, Clock, Config, Context, Data, Deferred, Duration, Effect, Equal, Exit, Fiber, FiberHandle, FiberSet, FileSystem, Layer, Option, Predicate, Queue, Ref, Result, Schedule, Schema, Semaphore, Stream, SubscriptionRef, identity } from "effect";
@@ -17,8 +17,7 @@ import { homedir, tmpdir } from "node:os";
17
17
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
18
18
  import lockfile from "proper-lockfile";
19
19
  import { BACKGROUND_CONTEXT, withAbortSignal } from "@earendil-works/chord/context";
20
- import { Type } from "@earendil-works/pi-ai";
21
- import { GenerationTask, Harness, ToolTask, createRegistry, defineDoc, defineExtension, defineTool, hook, section, watchEvents } from "@earendil-works/pi-durable";
20
+ import { GenerationTask, Harness, LiveDoc, ROOT_CONVERSATION_ID, ToolTask, createRegistry, defineDoc, defineExtension, defineTool, hook, section } from "@earendil-works/pi-durable";
22
21
  import { openNodeSqliteStorage } from "@earendil-works/pi-durable/storage/sqlite/node";
23
22
  import { ChildProcess, ChildProcessSpawner, CommandLine } from "effect/process";
24
23
  import { Worker } from "node:worker_threads";
@@ -38,12 +37,11 @@ import { constVoid } from "effect/Function";
38
37
  import { applyEdits, modify, parse as parse$1 } from "jsonc-parser";
39
38
  import { getStaticTOMLValue, parseTOML, traverseNodes } from "toml-eslint-parser";
40
39
  import { XMLParser } from "fast-xml-parser";
41
- import { isSea } from "node:sea";
42
40
  import * as ActionMcp from "@gjermundgaraba/effect-actions/ActionMcp";
43
41
  import * as Action from "@gjermundgaraba/effect-actions/Action";
44
42
  import { setup, types } from "xstate/fsm";
45
43
  // package.json
46
- var version$1 = "0.4.0";
44
+ var version$1 = "0.5.1";
47
45
  // src/ai/Setup.ts
48
46
  const Thinking = Schema.Literals([
49
47
  "off",
@@ -427,12 +425,12 @@ const withTarget = (pkg, target) => ({
427
425
  target
428
426
  });
429
427
  const isUnaudited = Schema.is(UnauditedEcosystem);
430
- const isApp = Schema.is(AppEcosystem);
428
+ const isApp$1 = Schema.is(AppEcosystem);
431
429
  const isRuntime = Schema.is(RuntimeEcosystem);
432
430
  const isUnauditedUpdate = (pkg) => isUnaudited(pkg.ecosystem);
433
- const isAppUpdate = (pkg) => isApp(pkg.ecosystem);
431
+ const isAppUpdate = (pkg) => isApp$1(pkg.ecosystem);
434
432
  const unauditedKind = (pkg) => {
435
- if (isApp(pkg.ecosystem)) return "app";
433
+ if (isApp$1(pkg.ecosystem)) return "app";
436
434
  if (isRuntime(pkg.ecosystem)) return "runtime";
437
435
  if (isUnaudited(pkg.ecosystem)) return "os";
438
436
  };
@@ -753,15 +751,15 @@ const Severity = Schema.Literals([
753
751
  const Finding = Schema.Struct({
754
752
  severity: Severity,
755
753
  title: Schema.String,
756
- detail: Schema.String,
757
- paths: Schema.Array(Schema.String)
754
+ detail: Schema.String.annotate({ description: "Markdown: the evidence and why it matters." }),
755
+ paths: Schema.Array(Schema.String).annotate({ description: "Workspace paths, with line ranges where useful." })
758
756
  });
759
757
  const Report = Schema.Struct({
760
758
  verdict: Verdict,
761
- rationale: Schema.String,
762
- summary: Schema.String,
759
+ rationale: Schema.String.annotate({ description: "One concrete sentence justifying the verdict." }),
760
+ summary: Schema.String.annotate({ description: "Markdown: what the update changes that bears on the mandate, what you flagged and why you cleared or kept it." }),
763
761
  findings: Schema.Array(Finding),
764
- unverified: Schema.Array(Schema.String)
762
+ unverified: Schema.Array(Schema.String).annotate({ description: "Each thing you could not verify." })
765
763
  });
766
764
  Schema.Struct({
767
765
  mode: Mode,
@@ -844,21 +842,23 @@ const descriptions = {
844
842
  grep: "Find a JavaScript regular expression in UTF-8 regular files below a path. Each line is matched whole. Lines over 1 KiB show a bounded window around each match with its file byte offset; a file stops at a line over 16 MiB.",
845
843
  list: "List workspace entries below a directory to a bounded depth."
846
844
  };
847
- const parameters = {
848
- read: {
849
- path: "Workspace-relative file path.",
850
- offset: "Zero-based byte offset; must be >= 0.",
851
- limit: `Maximum bytes to return; must be between 1 and ${limits$1.readBytes} inclusive.`
852
- },
853
- grep: {
854
- path: "Workspace-relative file or directory path.",
855
- pattern: "JavaScript regular expression."
856
- },
857
- list: {
858
- path: "Workspace-relative directory path; use . for the root.",
859
- depth: `Maximum directory depth; must be between 1 and ${limits$1.listDepth} inclusive.`
860
- }
861
- };
845
+ const count$1 = (maximum) => Schema.Number.pipe(Schema.check(Schema.isInt(), Schema.isBetween({
846
+ minimum: 1,
847
+ maximum
848
+ })));
849
+ const ReadArgs = Schema.Struct({
850
+ path: Schema.String.annotate({ description: "Workspace-relative file path." }),
851
+ offset: Schema.Number.pipe(Schema.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0))).annotate({ description: "Zero-based byte offset; must be >= 0." }),
852
+ limit: count$1(limits$1.readBytes).annotate({ description: `Maximum bytes to return; must be between 1 and ${limits$1.readBytes} inclusive.` })
853
+ });
854
+ const GrepArgs = Schema.Struct({
855
+ path: Schema.String.annotate({ description: "Workspace-relative file or directory path." }),
856
+ pattern: Schema.String.annotate({ description: "JavaScript regular expression." })
857
+ });
858
+ const ListArgs = Schema.Struct({
859
+ path: Schema.String.annotate({ description: "Workspace-relative directory path; use . for the root." }),
860
+ depth: count$1(limits$1.listDepth).annotate({ description: `Maximum directory depth; must be between 1 and ${limits$1.listDepth} inclusive.` })
861
+ });
862
862
  var ToolError = class extends Error {
863
863
  constructor(message) {
864
864
  super(message);
@@ -915,10 +915,6 @@ const locate$4 = async (workspace, name, context) => {
915
915
  return fail$1(`${context}: ${reason(error)}`);
916
916
  }
917
917
  };
918
- const byName = (left, right) => {
919
- if (left.name < right.name) return -1;
920
- return left.name > right.name ? 1 : 0;
921
- };
922
918
  const suffixOf = (entry) => {
923
919
  if (entry.isDirectory()) return "/";
924
920
  return entry.isSymbolicLink() ? "@" : "";
@@ -1008,7 +1004,7 @@ const list = async (workspace, args, signal) => await respond(signal, async () =
1008
1004
  return result === "" ? "no entries" : result;
1009
1005
  });
1010
1006
  const decodeAnswer = Schema.decodeUnknownOption(Schema.Union([Schema.Struct({ text: Schema.String }), Schema.Struct({ error: Schema.String })]));
1011
- const grepWorker = process.env["UPUP_GREP_WORKER"] ?? new URL(`grep-worker${path.extname(new URL(import.meta.url).pathname)}`, import.meta.url);
1007
+ const grepWorker = new URL(`grep-worker${path.extname(new URL(import.meta.url).pathname)}`, import.meta.url);
1012
1008
  const search = async (job, timeoutMs, signal) => {
1013
1009
  const { promise, resolve, reject } = Promise.withResolvers();
1014
1010
  const worker = new Worker(grepWorker);
@@ -1344,17 +1340,11 @@ const runDiff = (cwd, args, from, to, input) => Effect.callback((resume) => {
1344
1340
  });
1345
1341
  return Effect.sync(() => child.kill());
1346
1342
  });
1347
- const regularFiles = async (root, relative = "") => {
1348
- const entries = await readdir(path.join(root, relative)).catch(() => []);
1349
- const found = [];
1350
- for (const name of entries.toSorted()) {
1351
- const file = relative === "" ? name : `${relative}/${name}`;
1352
- const info = await lstat(path.join(root, file));
1353
- if (info.isDirectory()) found.push(...await regularFiles(root, file));
1354
- else if (info.isFile()) found.push(file);
1355
- }
1356
- return found;
1357
- };
1343
+ const regularFiles = (root, relative = "") => Effect.promise(async () => await readdir(path.join(root, relative), { withFileTypes: true }).catch(() => [])).pipe(Effect.flatMap((entries) => Effect.forEach(entries.toSorted(byName), (entry) => {
1344
+ const file = relative === "" ? entry.name : `${relative}/${entry.name}`;
1345
+ if (entry.isDirectory()) return regularFiles(root, file);
1346
+ return Effect.succeed(entry.isFile() ? [file] : []);
1347
+ }, { concurrency: "unbounded" })), Effect.map((found) => found.flat()));
1358
1348
  const failure$1 = (from, to) => (cause) => new DiffFailed({
1359
1349
  from,
1360
1350
  to,
@@ -1372,15 +1362,25 @@ const plain$1 = (pair) => ({
1372
1362
  paired: false,
1373
1363
  rewritten: false
1374
1364
  });
1375
- const planTree = async (workspace, from, to) => {
1376
- const [before, after] = await Promise.all([regularFiles(path.join(workspace, from)), regularFiles(path.join(workspace, to))]);
1365
+ const planTree = (workspace, from, to) => Effect.gen(function* () {
1366
+ const attempt = (run) => Effect.tryPromise({
1367
+ try: run,
1368
+ catch: failure$1(from, to)
1369
+ });
1370
+ const [before, after] = yield* Effect.all([regularFiles(path.join(workspace, from)), regularFiles(path.join(workspace, to))], { concurrency: "unbounded" });
1377
1371
  const beforeSet = new Set(before);
1378
1372
  const afterSet = new Set(after);
1379
1373
  const fromOnly = before.filter((file) => !afterSet.has(file));
1380
1374
  const toOnly = after.filter((file) => !beforeSet.has(file));
1381
- const only = /* @__PURE__ */ new Map();
1382
- for (const file of fromOnly) only.set(`from\0${file}`, await readFile(path.join(workspace, from, file)));
1383
- for (const file of toOnly) only.set(`to\0${file}`, await readFile(path.join(workspace, to, file)));
1375
+ const only = new Map(yield* Effect.forEach([...fromOnly.map((file) => ({
1376
+ side: "from",
1377
+ root: from,
1378
+ file
1379
+ })), ...toOnly.map((file) => ({
1380
+ side: "to",
1381
+ root: to,
1382
+ file
1383
+ }))], ({ side, root, file }) => attempt(async () => [`${side}\0${file}`, await readFile(path.join(workspace, root, file))]), { concurrency: 8 }));
1384
1384
  const pairs = matchRenames(fromOnly, toOnly, (side, file) => only.get(`${side}\0${file}`) ?? Buffer.alloc(0));
1385
1385
  const renames = renamesOf(pairs);
1386
1386
  const pairedFrom = new Set(pairs.map((pair) => pair.from));
@@ -1391,32 +1391,36 @@ const planTree = async (workspace, from, to) => {
1391
1391
  from: file,
1392
1392
  to: file
1393
1393
  }))];
1394
- for (const pair of candidates) {
1394
+ const classify = async (pair) => {
1395
1395
  const oldPath = path.join(workspace, from, pair.from);
1396
1396
  const nextPath = path.join(workspace, to, pair.to);
1397
1397
  const paired = pair.from !== pair.to;
1398
- if (!paired && renames.size === 0) {
1399
- if (!await identical(oldPath, nextPath)) changes.push(plain$1(pair));
1400
- continue;
1401
- }
1402
- const old = only.get(`from\0${pair.from}`) ?? await readFile(oldPath);
1403
- const next = only.get(`to\0${pair.to}`) ?? await readFile(nextPath);
1404
- if (!paired && old.equals(next)) continue;
1398
+ if (!paired && renames.size === 0) return await identical(oldPath, nextPath) ? void 0 : {
1399
+ same: false,
1400
+ change: plain$1(pair)
1401
+ };
1402
+ const [old, next] = await Promise.all([only.get(`from\0${pair.from}`) ?? readFile(oldPath), only.get(`to\0${pair.to}`) ?? readFile(nextPath)]);
1403
+ if (!paired && old.equals(next)) return;
1405
1404
  const text = isText(old) ? old.toString("latin1") : void 0;
1406
1405
  const rewrittenText = text === void 0 ? void 0 : rewrite(text, renames);
1407
1406
  const rewritten = rewrittenText !== void 0 && rewrittenText !== text;
1408
- if (!paired && !rewritten) {
1409
- changes.push(plain$1(pair));
1410
- continue;
1411
- }
1407
+ if (!paired && !rewritten) return {
1408
+ same: false,
1409
+ change: plain$1(pair)
1410
+ };
1412
1411
  const expected = rewrittenText === void 0 ? old : Buffer.from(rewrittenText, "latin1");
1413
- (expected.equals(next) ? same : changes).push({
1414
- ...pair,
1415
- expected,
1416
- paired,
1417
- rewritten
1418
- });
1419
- }
1412
+ return {
1413
+ same: expected.equals(next),
1414
+ change: {
1415
+ ...pair,
1416
+ expected,
1417
+ paired,
1418
+ rewritten
1419
+ }
1420
+ };
1421
+ };
1422
+ const planned = yield* Effect.forEach(candidates, (pair) => attempt(async () => await classify(pair)), { concurrency: 8 });
1423
+ for (const entry of planned) if (entry !== void 0) (entry.same ? same : changes).push(entry.change);
1420
1424
  for (const file of fromOnly) if (!pairedFrom.has(file)) changes.push({
1421
1425
  ...plain$1({
1422
1426
  from: file,
@@ -1438,7 +1442,7 @@ const planTree = async (workspace, from, to) => {
1438
1442
  }),
1439
1443
  same
1440
1444
  };
1441
- };
1445
+ });
1442
1446
  const mebibytes = (bytes) => `${Math.round(bytes / 1024 / 1024)} MiB`;
1443
1447
  const shownOmissions = 2e3;
1444
1448
  const changeDiff = (workspace, from, to, change) => {
@@ -1470,10 +1474,7 @@ const partial = (what, omitted) => omitted === "" ? "" : `The ${what} diff is pa
1470
1474
  const DiffBudget = Context.Reference("upup/DiffBudget", { defaultValue: () => () => maxDiffBytes });
1471
1475
  const treeDiff = (workspace, from, to, limit) => Effect.gen(function* () {
1472
1476
  const budget = limit ?? (yield* DiffBudget)(from);
1473
- const { changes, same } = yield* Effect.tryPromise({
1474
- try: async () => await planTree(workspace, from, to),
1475
- catch: failure$1(from, to)
1476
- });
1477
+ const { changes, same } = yield* planTree(workspace, from, to);
1477
1478
  const parts = [];
1478
1479
  const left = [];
1479
1480
  let size = 0;
@@ -1807,12 +1808,16 @@ const majorsOf = (from, to) => {
1807
1808
  };
1808
1809
  const exists$1 = async (file) => await stat(file).then(() => true, () => false);
1809
1810
  const emptyTree = async (directory) => await readdir(directory).then((entries) => entries.length === 0, () => false);
1810
- const readMajors = (workspace) => Effect.promise(async () => majorsOf(await listed$2(workspace, files.dependencyListFrom), await listed$2(workspace, files.dependencyListTo)));
1811
+ const majorsIn = async (workspace) => {
1812
+ const [from, to] = await Promise.all([listed$2(workspace, files.dependencyListFrom), listed$2(workspace, files.dependencyListTo)]);
1813
+ return majorsOf(from, to);
1814
+ };
1815
+ const readMajors = (workspace) => Effect.promise(async () => await majorsIn(workspace));
1811
1816
  const read$1 = (workspace) => Effect.gen(function* () {
1812
1817
  const meta = yield* readMeta(workspace);
1813
1818
  return yield* Effect.tryPromise({
1814
1819
  try: async () => {
1815
- const diff = await readFile(path.join(workspace, files.diff));
1820
+ const [diff, majors] = await Promise.all([readFile(path.join(workspace, files.diff)), majorsIn(workspace)]);
1816
1821
  const trees = [];
1817
1822
  const titled = [];
1818
1823
  const targets = /* @__PURE__ */ new Map();
@@ -1851,7 +1856,7 @@ const read$1 = (workspace) => Effect.gen(function* () {
1851
1856
  trees,
1852
1857
  files: titled,
1853
1858
  sections,
1854
- majors: majorsOf(await listed$2(workspace, files.dependencyListFrom), await listed$2(workspace, files.dependencyListTo))
1859
+ majors
1855
1860
  };
1856
1861
  },
1857
1862
  catch: failed$1(workspace)
@@ -1921,28 +1926,18 @@ const BriefDoc = defineDoc({
1921
1926
  initial: () => ({ brief: null }),
1922
1927
  checkpointWhen: () => false
1923
1928
  });
1924
- const severity = Type.Union([
1925
- Type.Literal("info"),
1926
- Type.Literal("low"),
1927
- Type.Literal("medium"),
1928
- Type.Literal("high")
1929
- ]);
1930
- const ReportParameters = Type.Object({
1931
- verdict: Type.Union([
1932
- Type.Literal("ok"),
1933
- Type.Literal("caution"),
1934
- Type.Literal("danger"),
1935
- Type.Literal("no-verdict")
1936
- ]),
1937
- rationale: Type.String({ description: "One concrete sentence justifying the verdict." }),
1938
- summary: Type.String({ description: "Markdown: what the update changes that bears on the mandate, what you flagged and why you cleared or kept it." }),
1939
- findings: Type.Array(Type.Object({
1940
- severity,
1941
- title: Type.String(),
1942
- detail: Type.String({ description: "Markdown: the evidence and why it matters." }),
1943
- paths: Type.Array(Type.String(), { description: "Workspace paths, with line ranges where useful." })
1929
+ const parameters = (schema) => Schema.toJsonSchemaDocument(schema).schema;
1930
+ const decodeRead = Schema.decodeUnknownSync(ReadArgs);
1931
+ const decodeGrep = Schema.decodeUnknownSync(GrepArgs);
1932
+ const decodeList = Schema.decodeUnknownSync(ListArgs);
1933
+ const decodeSubmitted = Schema.decodeUnknownSync(Report);
1934
+ const encodeReport = (submitted) => ({
1935
+ ...submitted,
1936
+ findings: submitted.findings.map((finding) => ({
1937
+ ...finding,
1938
+ paths: [...finding.paths]
1944
1939
  })),
1945
- unverified: Type.Array(Type.String(), { description: "Each thing you could not verify." })
1940
+ unverified: [...submitted.unverified]
1946
1941
  });
1947
1942
  const ReportDoc = defineDoc({
1948
1943
  kind: "upup.report",
@@ -1968,42 +1963,33 @@ const auditExtension = (workspace) => {
1968
1963
  name: "read",
1969
1964
  description: descriptions.read,
1970
1965
  replay: "safe",
1971
- parameters: Type.Object({
1972
- path: Type.String({ description: parameters.read.path }),
1973
- offset: Type.Integer({ description: parameters.read.offset }),
1974
- limit: Type.Integer({ description: parameters.read.limit })
1975
- }),
1976
- execute: async (args, _api, invocation) => answer(await read$2(workspace, args, invocation.abortSignal))
1966
+ parameters: parameters(ReadArgs),
1967
+ execute: async (args, _api, invocation) => answer(await read$2(workspace, decodeRead(args), invocation.abortSignal))
1977
1968
  });
1978
1969
  const grep$1 = defineTool({
1979
1970
  name: "grep",
1980
1971
  description: descriptions.grep,
1981
1972
  replay: "safe",
1982
- parameters: Type.Object({
1983
- path: Type.String({ description: parameters.grep.path }),
1984
- pattern: Type.String({ description: parameters.grep.pattern })
1985
- }),
1986
- execute: async (args, _api, invocation) => answer(await grep(workspace, args, invocation.abortSignal === void 0 ? {} : { signal: invocation.abortSignal }))
1973
+ parameters: parameters(GrepArgs),
1974
+ execute: async (args, _api, invocation) => answer(await grep(workspace, decodeGrep(args), invocation.abortSignal === void 0 ? {} : { signal: invocation.abortSignal }))
1987
1975
  });
1988
1976
  const list$1 = defineTool({
1989
1977
  name: "list",
1990
1978
  description: descriptions.list,
1991
1979
  replay: "safe",
1992
- parameters: Type.Object({
1993
- path: Type.String({ description: parameters.list.path }),
1994
- depth: Type.Integer({ description: parameters.list.depth })
1995
- }),
1996
- execute: async (args, _api, invocation) => answer(await list(workspace, args, invocation.abortSignal))
1980
+ parameters: parameters(ListArgs),
1981
+ execute: async (args, _api, invocation) => answer(await list(workspace, decodeList(args), invocation.abortSignal))
1997
1982
  });
1998
1983
  const submit = defineTool({
1999
1984
  name: "submit_report",
2000
1985
  description: "Submit the audit report. Call exactly once, when the investigation is done; the audit ends.",
2001
1986
  replay: "safe",
2002
- parameters: ReportParameters,
1987
+ parameters: parameters(Report),
2003
1988
  execute: async (args, api, invocation) => {
1989
+ const encoded = encodeReport(decodeSubmitted(args));
2004
1990
  await api.commit(async (tx) => {
2005
1991
  const doc = await tx.doc(ReportDoc, api.conversationId);
2006
- doc.report = structuredClone(args);
1992
+ doc.report = encoded;
2007
1993
  }, invocation);
2008
1994
  return {
2009
1995
  ...text$2("Report submitted."),
@@ -2079,6 +2065,32 @@ const entriesOf$1 = (message) => {
2079
2065
  }
2080
2066
  return [];
2081
2067
  };
2068
+ const TextBlock = Schema.Struct({
2069
+ type: Schema.Literal("text"),
2070
+ text: Schema.String
2071
+ });
2072
+ const ThinkingBlock = Schema.Struct({
2073
+ type: Schema.Literal("thinking"),
2074
+ thinking: Schema.String
2075
+ });
2076
+ const isTextBlock = Schema.is(TextBlock);
2077
+ const isThinkingBlock = Schema.is(ThinkingBlock);
2078
+ const decodeLive = Schema.decodeUnknownOption(Schema.Struct({ generation: Schema.optional(Schema.Struct({
2079
+ attempt: Schema.Finite,
2080
+ message: Schema.optional(Schema.Struct({ content: Schema.Array(Schema.Unknown) })),
2081
+ retry: Schema.optional(Schema.Struct({ error: Schema.String }))
2082
+ })) }));
2083
+ const streamed = (block) => {
2084
+ if (isThinkingBlock(block)) return block.thinking.trim() === "" ? [] : [{
2085
+ kind: "thinking",
2086
+ text: block.thinking
2087
+ }];
2088
+ if (isTextBlock(block)) return block.text.trim() === "" ? [] : [{
2089
+ kind: "text",
2090
+ text: block.text
2091
+ }];
2092
+ return [];
2093
+ };
2082
2094
  var Transcript = class {
2083
2095
  committed = /* @__PURE__ */ new Map();
2084
2096
  live = [];
@@ -2086,41 +2098,20 @@ var Transcript = class {
2086
2098
  add(entry) {
2087
2099
  this.committed.set(entry.id, (entry.model ?? []).flatMap(entriesOf$1));
2088
2100
  }
2089
- apply(event) {
2090
- switch (event.type) {
2091
- case "snapshot":
2092
- this.committed.clear();
2093
- for (const entry of event.entries) this.add(entry);
2094
- this.live = [];
2095
- break;
2096
- case "entry_appended":
2097
- case "message_end":
2098
- this.add(event.entry);
2099
- this.live = [];
2100
- this.retry = void 0;
2101
- break;
2102
- case "message_update":
2103
- for (const change of event.changes) if (change.type === "text_delta" || change.type === "thinking_delta") {
2104
- const kind = change.type === "text_delta" ? "text" : "thinking";
2105
- const last = this.live.at(-1);
2106
- if (last?.kind === kind) this.live[this.live.length - 1] = {
2107
- kind,
2108
- text: last.text + change.delta
2109
- };
2110
- else this.live.push({
2111
- kind,
2112
- text: change.delta
2113
- });
2114
- }
2115
- break;
2116
- case "auto_retry_start":
2117
- this.retry = {
2118
- kind: "retry",
2119
- text: `retrying (attempt ${event.attempt}): ${event.errorMessage}`
2120
- };
2121
- break;
2122
- case "auto_retry_end": this.retry = void 0;
2123
- }
2101
+ view(view) {
2102
+ for (const entry of view.entries) this.add(entry);
2103
+ const generation = decodeLive(view.docs[LiveDoc.definition.kind]).pipe(Option.flatMapNullishOr((live) => live.generation));
2104
+ this.live = Option.match(generation, {
2105
+ onNone: () => [],
2106
+ onSome: ({ message }) => (message?.content ?? []).flatMap(streamed)
2107
+ });
2108
+ this.retry = Option.match(generation, {
2109
+ onNone: () => void 0,
2110
+ onSome: ({ attempt, retry }) => retry === void 0 ? void 0 : {
2111
+ kind: "retry",
2112
+ text: `retrying (attempt ${attempt}): ${retry.error}`
2113
+ }
2114
+ });
2124
2115
  }
2125
2116
  entries() {
2126
2117
  return [
@@ -2135,16 +2126,24 @@ const attempt$1 = (evaluate) => Effect.tryPromise({
2135
2126
  try: evaluate,
2136
2127
  catch: failed
2137
2128
  });
2129
+ const watched = (open, onValue) => Effect.acquireRelease(attempt$1(async () => {
2130
+ const watch = await open();
2131
+ watch.start(async (call) => {
2132
+ if (call.kind === "value") onValue(call.value);
2133
+ });
2134
+ return watch;
2135
+ }), (watch) => Effect.promise(async () => await watch.stop()).pipe(Effect.ignore));
2138
2136
  const lastAssistant = (entries) => entries.flatMap((entry) => entry.model ?? []).findLast((message) => message.role === "assistant");
2139
- const openHarness = (file, workspace, models) => Effect.acquireRelease(attempt$1(async () => {
2140
- if (workspace === "" && !existsSync(file)) throw new Error(`no audit at ${file}`);
2141
- const extension = auditExtension(workspace);
2137
+ const openHarness = (file, models, workspace) => Effect.acquireRelease(attempt$1(async () => {
2138
+ if (workspace === void 0 && !existsSync(file)) throw new Error(`no audit at ${file}`);
2139
+ const extension = auditExtension(workspace ?? "");
2142
2140
  const registry = createRegistry();
2143
2141
  registry.install(extension);
2144
2142
  return await Harness.open(await openNodeSqliteStorage(file), {
2145
2143
  models,
2146
2144
  registry,
2147
- settings: { extensions: [extension] }
2145
+ settings: { extensions: [extension] },
2146
+ readOnly: workspace === void 0
2148
2147
  }, context);
2149
2148
  }), (harness) => Effect.promise(async () => {
2150
2149
  await harness.close(context);
@@ -2157,7 +2156,7 @@ const encodeBrief = (brief) => ({
2157
2156
  artifacts: [...brief.artifacts]
2158
2157
  });
2159
2158
  const run$5 = (options) => Effect.scoped(Effect.gen(function* () {
2160
- const harness = yield* openHarness(options.file, options.brief.workspace, options.models);
2159
+ const harness = yield* openHarness(options.file, options.models, options.brief.workspace);
2161
2160
  const root = yield* attempt$1(async () => await harness.root(context, {
2162
2161
  agent: {
2163
2162
  model: {
@@ -2172,13 +2171,12 @@ const run$5 = (options) => Effect.scoped(Effect.gen(function* () {
2172
2171
  }
2173
2172
  }));
2174
2173
  const transcript = new Transcript();
2175
- const events = yield* Effect.acquireRelease(attempt$1(async () => await watchEvents(harness, root.id, context)), (stream) => Effect.promise(async () => await stream.stop()).pipe(Effect.ignore));
2176
- transcript.apply(events.snapshot);
2177
- options.onTranscript(transcript.entries());
2178
- events.start(async (batch) => {
2179
- for (const event of batch) transcript.apply(event);
2174
+ const views = yield* watched(async () => await root.watch(context), (view) => {
2175
+ transcript.view(view);
2180
2176
  options.onTranscript(transcript.entries());
2181
2177
  });
2178
+ transcript.view(views.value);
2179
+ options.onTranscript(transcript.entries());
2182
2180
  harness.resume();
2183
2181
  const settled = yield* Effect.tryPromise({
2184
2182
  try: async (signal) => {
@@ -2205,20 +2203,29 @@ const run$5 = (options) => Effect.scoped(Effect.gen(function* () {
2205
2203
  _tag: "Reported",
2206
2204
  report: decoded.value
2207
2205
  };
2208
- const final = yield* attempt$1(async () => await watchEvents(harness, root.id, context));
2209
- yield* attempt$1(async () => await final.stop());
2206
+ const final = yield* attempt$1(async () => await root.context(context));
2210
2207
  if (settled.value.status === "unanswered") return {
2211
2208
  _tag: "Failed",
2212
2209
  issue: Predicate.isString(settled.value.detail) ? settled.value.detail : settled.value.reason
2213
2210
  };
2214
2211
  return {
2215
2212
  _tag: "Failed",
2216
- issue: lastAssistant(final.snapshot.entries)?.errorMessage ?? "the model finished without submitting a report"
2213
+ issue: lastAssistant(final.entries)?.errorMessage ?? "the model finished without submitting a report"
2217
2214
  };
2218
2215
  }));
2216
+ const storedRoot = (file, models) => Effect.gen(function* () {
2217
+ const harness = yield* openHarness(file, models);
2218
+ return {
2219
+ harness,
2220
+ root: yield* attempt$1(async () => await harness.conversation(ROOT_CONVERSATION_ID, context))
2221
+ };
2222
+ });
2219
2223
  const stored = (file, models) => Effect.scoped(Effect.gen(function* () {
2220
- const harness = yield* openHarness(file, "", models);
2221
- const root = yield* attempt$1(async () => await harness.root(context));
2224
+ const { harness, root } = yield* storedRoot(file, models);
2225
+ if (root === void 0) return {
2226
+ brief: Option.none(),
2227
+ report: Option.none()
2228
+ };
2222
2229
  const brief = yield* attempt$1(async () => await harness.snapshot(BriefDoc, root.id, context));
2223
2230
  const submitted = yield* attempt$1(async () => await harness.snapshot(ReportDoc, root.id, context));
2224
2231
  return {
@@ -2227,12 +2234,12 @@ const stored = (file, models) => Effect.scoped(Effect.gen(function* () {
2227
2234
  };
2228
2235
  }));
2229
2236
  const transcript = (file, models) => Effect.scoped(Effect.gen(function* () {
2230
- const harness = yield* openHarness(file, "", models);
2231
- const root = yield* attempt$1(async () => await harness.root(context));
2232
- const events = yield* attempt$1(async () => await watchEvents(harness, root.id, context));
2233
- yield* attempt$1(async () => await events.stop());
2237
+ const { root } = yield* storedRoot(file, models);
2234
2238
  const built = new Transcript();
2235
- built.apply(events.snapshot);
2239
+ if (root !== void 0) {
2240
+ const active = yield* attempt$1(async () => await root.context(context));
2241
+ for (const entry of active.entries) built.add(entry);
2242
+ }
2236
2243
  return built.entries();
2237
2244
  }));
2238
2245
  // src/inventory/versions.ts
@@ -2339,7 +2346,7 @@ const escape = (path) => path.replaceAll(/[A-Z]/gu, (letter) => `!${letter.toLow
2339
2346
  const deprecation = (mod) => Option.fromNullishOr(/^\/\/\s*Deprecated:\s*(?<reason>.+)$/mu.exec(mod)?.groups?.["reason"]?.trim());
2340
2347
  const lookup$5 = Effect.fn("go.lookup")(function* (client, wanted) {
2341
2348
  const base = `https://proxy.golang.org/${escape(wanted.name)}/@v`;
2342
- const [latest, infos] = yield* Effect.all([getJson(client, `https://proxy.golang.org/${escape(wanted.name)}/@latest`, Info$2), Effect.forEach(wanted.versions, (version) => getJson(client, `${base}/${escape(version)}.info`, Info$2).pipe(Effect.option), { concurrency: 2 })], { concurrency: 2 });
2349
+ const [latest, infos] = yield* Effect.all([getJson(client, `https://proxy.golang.org/${escape(wanted.name)}/@latest`, Info$2), Effect.forEach(wanted.versions, (version) => getJson(client, `${base}/${escape(version)}.info`, Info$2).pipe(Effect.option), { concurrency: 2 })], { concurrency: "unbounded" });
2343
2350
  const mod = yield* getText(client, `${base}/${escape(latest.Version)}.mod`);
2344
2351
  const deprecated = deprecation(mod);
2345
2352
  const found = infos.flatMap((info) => Option.isSome(info) ? [info.value] : []);
@@ -4850,30 +4857,36 @@ const resolveFormula = Effect.fn("brew.resolveFormula")(function* (client, sourc
4850
4857
  digest: createHash("sha256").update(body).digest("hex")
4851
4858
  };
4852
4859
  });
4853
- let to;
4854
- let from;
4855
- if (source.tapGitHead !== "") {
4856
- const current = yield* Effect.option(snapshot(source.tapGitHead, "tap revision reported by brew info"));
4857
- if (current._tag === "Some" && matchesVersion(current.value.snapshot.text, toVersion) && (source.rubySourceChecksum === "" || source.rubySourceChecksum.toLowerCase() === current.value.digest)) to = current.value.snapshot;
4858
- }
4859
- let endpoint = `${githubApi}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits?${new URLSearchParams({
4860
- path: source.rubySourcePath,
4861
- per_page: `${historyPageSize}`
4862
- }).toString()}`;
4863
- let scanned = 0;
4864
- const complete = () => from !== void 0 && to !== void 0;
4865
- for (let page = 0; endpoint !== "" && page < maxHistoryPages && !complete(); page += 1) {
4866
- const { body, link } = yield* githubGet(client, endpoint, token).pipe(Effect.mapError(prefixed("query brew formula history")));
4867
- const commits = yield* commitsOf(body, endpoint);
4868
- for (const commit of commits) {
4869
- scanned += 1;
4870
- const { snapshot: candidate } = yield* snapshot(commit.sha, commit.message);
4871
- if (to === void 0 && matchesVersion(candidate.text, toVersion)) to = candidate;
4872
- if (from === void 0 && matchesVersion(candidate.text, fromVersion)) from = candidate;
4873
- if (complete()) break;
4860
+ const scanHistory = Effect.gen(function* () {
4861
+ let to;
4862
+ let from;
4863
+ let endpoint = `${githubApi}/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits?${new URLSearchParams({
4864
+ path: source.rubySourcePath,
4865
+ per_page: `${historyPageSize}`
4866
+ }).toString()}`;
4867
+ let scanned = 0;
4868
+ const complete = () => from !== void 0 && to !== void 0;
4869
+ for (let page = 0; endpoint !== "" && page < maxHistoryPages && !complete(); page += 1) {
4870
+ const { body, link } = yield* githubGet(client, endpoint, token).pipe(Effect.mapError(prefixed("query brew formula history")));
4871
+ const commits = yield* commitsOf(body, endpoint);
4872
+ for (const commit of commits) {
4873
+ scanned += 1;
4874
+ const { snapshot: candidate } = yield* snapshot(commit.sha, commit.message);
4875
+ if (to === void 0 && matchesVersion(candidate.text, toVersion)) to = candidate;
4876
+ if (from === void 0 && matchesVersion(candidate.text, fromVersion)) from = candidate;
4877
+ if (complete()) break;
4878
+ }
4879
+ endpoint = complete() ? "" : nextPage(endpoint, link);
4874
4880
  }
4875
- endpoint = complete() ? "" : nextPage(endpoint, link);
4876
- }
4881
+ return {
4882
+ from,
4883
+ to,
4884
+ scanned
4885
+ };
4886
+ });
4887
+ const [current, history] = yield* Effect.all([source.tapGitHead === "" ? Effect.succeedNone : Effect.option(snapshot(source.tapGitHead, "tap revision reported by brew info")), scanHistory], { concurrency: "unbounded" });
4888
+ const { from, scanned } = history;
4889
+ const to = current._tag === "Some" && matchesVersion(current.value.snapshot.text, toVersion) && (source.rubySourceChecksum === "" || source.rubySourceChecksum.toLowerCase() === current.value.digest) ? current.value.snapshot : history.to;
4877
4890
  if (to === void 0) return yield* new EvidenceUnavailable({
4878
4891
  source: "brew",
4879
4892
  issue: `brew formula history has no snapshot for target version ${toVersion} within the newest ${scanned} commits`
@@ -5278,13 +5291,14 @@ const payloadDiff = Effect.fn("brew.payloadDiff")(function* (client, workspace,
5278
5291
  const { name } = shortName(artifact);
5279
5292
  const oldStrip = yield* strip(name, plan.old);
5280
5293
  const newStrip = yield* strip(name, plan.new);
5281
- const oldManifest = yield* payloadManifest(client, "installed", plan.old, oldStrip, path.join(workspace, files.payloadTreeFrom));
5294
+ const [oldManifest, newManifest] = yield* Effect.all([payloadManifest(client, "installed", plan.old, oldStrip, path.join(workspace, files.payloadTreeFrom)), payloadManifest(client, "target", plan.new, newStrip, path.join(workspace, files.payloadTreeTo))], { concurrency: "unbounded" });
5282
5295
  if (oldManifest === void 0) return yield* unavailablePayload(workspace, "installed Homebrew payload archive format is unsupported");
5283
- const newManifest = yield* payloadManifest(client, "target", plan.new, newStrip, path.join(workspace, files.payloadTreeTo));
5284
5296
  if (newManifest === void 0) return yield* unavailablePayload(workspace, "target Homebrew payload archive format is unsupported");
5285
- const manifests = yield* writeFileDiff(workspace, files.payloadFrom, files.payloadTo, manifestJson(oldManifest), manifestJson(newManifest));
5286
- const binaries = yield* writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(oldManifest)), json(binarySummaries(newManifest)));
5287
- const trees = yield* treeDiff(workspace, files.payloadTreeFrom, files.payloadTreeTo);
5297
+ const [manifests, binaries, trees] = yield* Effect.all([
5298
+ writeFileDiff(workspace, files.payloadFrom, files.payloadTo, manifestJson(oldManifest), manifestJson(newManifest)),
5299
+ writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(oldManifest)), json(binarySummaries(newManifest))),
5300
+ treeDiff(workspace, files.payloadTreeFrom, files.payloadTreeTo)
5301
+ ], { concurrency: "unbounded" });
5288
5302
  const contents = trees.diff;
5289
5303
  const contentDetail = [" Extracted payload file contents are diffed.", partial("payload", trees.omitted)].filter((sentence) => sentence !== "").join(" ");
5290
5304
  const origin = plan.old.origin === "" ? "" : ` (pinned by ${plan.old.origin})`;
@@ -5763,9 +5777,9 @@ const writeChanges = Effect.fn("git.writeChanges")(function* (from, to, destinat
5763
5777
  modes
5764
5778
  };
5765
5779
  const contents = readBatch((yield* git(["cat-file", "--batch"], objects.map((object) => `${object}\n`).join(""))).stdout, objects);
5766
- yield* Effect.tryPromise({
5780
+ yield* Effect.forEach(changes, (change) => Effect.tryPromise({
5767
5781
  try: async () => {
5768
- for (const change of changes) for (const [object, root] of [[change.fromObject, destination.from], [change.toObject, destination.to]]) {
5782
+ for (const [object, root] of [[change.fromObject, destination.from], [change.toObject, destination.to]]) {
5769
5783
  if (object === void 0) continue;
5770
5784
  const file = path.join(root, change.path);
5771
5785
  await mkdir(path.dirname(file), {
@@ -5779,6 +5793,9 @@ const writeChanges = Effect.fn("git.writeChanges")(function* (from, to, destinat
5779
5793
  repository,
5780
5794
  issue: `write source files: ${String(error)}`
5781
5795
  })
5796
+ }), {
5797
+ concurrency: 8,
5798
+ discard: true
5782
5799
  });
5783
5800
  return {
5784
5801
  files: changes.length,
@@ -5839,9 +5856,9 @@ const moduleChanges = (from, to, released) => {
5839
5856
  };
5840
5857
  };
5841
5858
  const readSummaries = (workspace, file) => Effect.tryPromise(async () => await readFile(path.join(workspace, file), "utf-8")).pipe(Effect.flatMap((text) => Schema.decodeEffect(Summaries)(text)), Effect.option);
5859
+ const readBinarySummaries = (workspace) => Effect.all([readSummaries(workspace, files.binaryFrom), readSummaries(workspace, files.binaryTo)], { concurrency: "unbounded" });
5842
5860
  const goSourceEvidence = Effect.fn("goSource.evidence")(function* (client, workspace, released) {
5843
- const from = yield* readSummaries(workspace, files.binaryFrom);
5844
- const to = yield* readSummaries(workspace, files.binaryTo);
5861
+ const [from, to] = yield* readBinarySummaries(workspace);
5845
5862
  if (from._tag === "None" || to._tag === "None") return;
5846
5863
  const { changes, reason } = moduleChanges(from.value, to.value, released);
5847
5864
  if (changes.length === 0) return {
@@ -5853,7 +5870,7 @@ const goSourceEvidence = Effect.fn("goSource.evidence")(function* (client, works
5853
5870
  const plan = yield* resolve$3(client, "go", modulePath, version);
5854
5871
  return yield* materialize$2(client, plan, path.join(workspace, tree, modulePath));
5855
5872
  });
5856
- const fetched = yield* Effect.forEach(changes, (change) => Effect.result(Effect.all([fetch(change.path, change.from, files.goSourceFrom), fetch(change.path, change.to, files.goSourceTo)], { concurrency: 2 })), { concurrency: 2 });
5873
+ const fetched = yield* Effect.forEach(changes, (change) => Effect.result(Effect.all([fetch(change.path, change.from, files.goSourceFrom), fetch(change.path, change.to, files.goSourceTo)], { concurrency: "unbounded" })), { concurrency: 2 });
5857
5874
  const failures = changes.flatMap((change, index) => {
5858
5875
  const result = fetched[index];
5859
5876
  return result?._tag === "Failure" ? [`${change.path}: ${result.failure.issue}`] : [];
@@ -5912,8 +5929,7 @@ const buildInfoSources = (from, to) => {
5912
5929
  return [...sources.values()].slice(0, 4);
5913
5930
  };
5914
5931
  const readBuildInfoSources = Effect.fn("goSource.buildInfoSources")(function* (workspace) {
5915
- const from = yield* readSummaries(workspace, files.binaryFrom);
5916
- const to = yield* readSummaries(workspace, files.binaryTo);
5932
+ const [from, to] = yield* readBinarySummaries(workspace);
5917
5933
  return from._tag === "None" || to._tag === "None" ? [] : buildInfoSources(from.value, to.value);
5918
5934
  });
5919
5935
  // src/audit/source-evidence.ts
@@ -6225,7 +6241,7 @@ const releaseAssetSources = Effect.fn("sourceLink.releaseAssets")(function* (cli
6225
6241
  } })), Effect.catch((error) => Effect.succeed(gap(error.issue))));
6226
6242
  }
6227
6243
  return Effect.succeed(gap("no release of the repository publishes this exact binary"));
6228
- });
6244
+ }, { concurrency: 4 });
6229
6245
  });
6230
6246
  // src/audit/brew.ts
6231
6247
  const caskArchiveUnavailable = "compiled cask payloads are not source archives";
@@ -6291,7 +6307,7 @@ const sourceDiff = Effect.fn("brew.sourceDiff")(function* (client, workspace, pa
6291
6307
  const [gap] = yield* Effect.all([sourceTree(client, pair.old, path.join(workspace, files.sourceFrom)).pipe(Effect.as(""), Effect.catch((error) => {
6292
6308
  const reason = historicalGap(pair.old.url, error);
6293
6309
  return reason === void 0 ? Effect.fail(labelled("download old brew source archive")(error)) : Effect.succeed(reason);
6294
- })), sourceTree(client, pair.new, path.join(workspace, files.source)).pipe(Effect.mapError(labelled("download new brew source archive")))], { concurrency: 2 });
6310
+ })), sourceTree(client, pair.new, path.join(workspace, files.source)).pipe(Effect.mapError(labelled("download new brew source archive")))], { concurrency: "unbounded" });
6295
6311
  if (gap !== "") return {
6296
6312
  diff: Buffer.alloc(0),
6297
6313
  reason: gap,
@@ -6328,9 +6344,11 @@ const sourceEvidence = Effect.fn("brew.sourceEvidence")(function* (client, works
6328
6344
  };
6329
6345
  });
6330
6346
  const materialize$1 = Effect.fn("brew.materialize")(function* (client, workspace, identity, plan, key) {
6331
- const formula = yield* materializeFormula(workspace, plan.formula);
6332
- const source = yield* sourceEvidence(client, workspace, archives(plan.formula), plan.sourceGap);
6333
- const payload = yield* materializePayload(client, workspace, identity.delta.artifact, plan.payload);
6347
+ const [formula, source, payload] = yield* Effect.all([
6348
+ materializeFormula(workspace, plan.formula),
6349
+ sourceEvidence(client, workspace, archives(plan.formula), plan.sourceGap),
6350
+ materializePayload(client, workspace, identity.delta.artifact, plan.payload)
6351
+ ], { concurrency: "unbounded" });
6334
6352
  const goSource = source.included ? void 0 : yield* goSourceEvidence(client, workspace, identity.delta);
6335
6353
  const sources = goSource?.included === true || source.included ? [] : [...plan.repository === void 0 ? [] : [plan.repository], ...yield* readBuildInfoSources(workspace)];
6336
6354
  const repository = sources.length === 0 ? void 0 : yield* materializeSources(workspace, sources);
@@ -6357,7 +6375,7 @@ const resolve$2 = Effect.fn("brew.resolve")(function* (client, identity) {
6357
6375
  const formulaGap = formula.fromGap === "" ? archiveUnavailableReason(archives(formula)) : "the installed version's formula snapshot is unavailable";
6358
6376
  const sourceGap = kind === "cask" ? caskArchiveUnavailable : formulaGap;
6359
6377
  const payload = yield* resolvePayload(info, artifact, from, to, formula.from?.text);
6360
- const released = sourceGap !== "" && payload.old.url !== "" && payload.new.url !== "" ? yield* Effect.all([releaseTagSource(payload.old.url), releaseTagSource(payload.new.url)], { concurrency: 2 }) : void 0;
6378
+ const released = sourceGap !== "" && payload.old.url !== "" && payload.new.url !== "" ? yield* Effect.all([releaseTagSource(payload.old.url), releaseTagSource(payload.new.url)], { concurrency: "unbounded" }) : void 0;
6361
6379
  const repository = released === void 0 || released.every((side) => "gap" in side) ? void 0 : {
6362
6380
  label: artifact,
6363
6381
  from: released[0],
@@ -6422,7 +6440,7 @@ const workspaceOf$1 = Effect.fn("githubActions.workspace")(function* (workspace,
6422
6440
  const githubActionPreparer = (repositoryOf, options = {}) => Effect.fn("githubActions.prepare")(function* (_client, identity) {
6423
6441
  const { artifact, from, to } = identity.delta;
6424
6442
  const repository = repositoryOf(artifact);
6425
- const [fromCommit, toCommit] = yield* Effect.all([tagCommit(repository, from, options), tagCommit(repository, to, options)], { concurrency: 2 }).pipe(Effect.mapError(unavailable$1));
6443
+ const [fromCommit, toCommit] = yield* Effect.all([tagCommit(repository, from, options), tagCommit(repository, to, options)], { concurrency: "unbounded" }).pipe(Effect.mapError(unavailable$1));
6426
6444
  const listed = identity.context["revision"];
6427
6445
  if (listed !== toCommit) return yield* new EvidenceUnavailable({
6428
6446
  source: repository,
@@ -6619,12 +6637,14 @@ const pypiWorkspace = Effect.fn("pypi.workspace")(function* (client, workspace,
6619
6637
  issue: error instanceof Error ? error.message : String(error)
6620
6638
  })
6621
6639
  });
6622
- const [from, to] = yield* Effect.all([materialize(client, plans.from, path.join(workspace, files.from), path.join(workspace, files.wheelFrom)), materialize(client, plans.to, path.join(workspace, files.to), path.join(workspace, files.wheelTo))], { concurrency: 2 });
6623
- const sources = yield* treeDiff(workspace, files.from, files.to);
6624
- const records = yield* writeFileDiff(workspace, files.pypiFrom, files.pypiTo, manifestJson(from), manifestJson(to));
6625
- const sourceBinaries = yield* writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(from.publisher_sdist?.archive_manifest)), json(binarySummaries(to.publisher_sdist?.archive_manifest)));
6626
- const wheels = yield* treeDiff(workspace, files.wheelFrom, files.wheelTo);
6627
- const wheelBinaries = yield* writeFileDiff(workspace, files.binaryWheelFrom, files.binaryWheelTo, json(binarySummaries(from.compatible_universal_wheel?.archive_manifest)), json(binarySummaries(to.compatible_universal_wheel?.archive_manifest)));
6640
+ const [from, to] = yield* Effect.all([materialize(client, plans.from, path.join(workspace, files.from), path.join(workspace, files.wheelFrom)), materialize(client, plans.to, path.join(workspace, files.to), path.join(workspace, files.wheelTo))], { concurrency: "unbounded" });
6641
+ const [sources, records, sourceBinaries, wheels, wheelBinaries] = yield* Effect.all([
6642
+ treeDiff(workspace, files.from, files.to),
6643
+ writeFileDiff(workspace, files.pypiFrom, files.pypiTo, manifestJson(from), manifestJson(to)),
6644
+ writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(from.publisher_sdist?.archive_manifest)), json(binarySummaries(to.publisher_sdist?.archive_manifest))),
6645
+ treeDiff(workspace, files.wheelFrom, files.wheelTo),
6646
+ writeFileDiff(workspace, files.binaryWheelFrom, files.binaryWheelTo, json(binarySummaries(from.compatible_universal_wheel?.archive_manifest)), json(binarySummaries(to.compatible_universal_wheel?.archive_manifest)))
6647
+ ], { concurrency: "unbounded" });
6628
6648
  const detail = `Checksum-verified PyPI publisher artifacts; ${pairedDetail("source distributions", from.publisher_sdist, to.publisher_sdist)}; ${pairedDetail("compatible universal wheel candidates", from.compatible_universal_wheel, to.compatible_universal_wheel)}; the installer’s exact resolver selection is not known.`;
6629
6649
  return yield* write(workspace, identity, Buffer.concat([
6630
6650
  sources.diff,
@@ -6641,7 +6661,7 @@ const pypiWorkspace = Effect.fn("pypi.workspace")(function* (client, workspace,
6641
6661
  const preparePyPI = Effect.fn("pypi.prepare")(function* (client, identity) {
6642
6662
  const { artifact, from, to } = identity.delta;
6643
6663
  const python = identity.context["python"] ?? "";
6644
- const [fromPlan, toPlan] = yield* Effect.all([resolve$1(client, artifact, from, python), resolve$1(client, artifact, to, python)], { concurrency: 2 });
6664
+ const [fromPlan, toPlan] = yield* Effect.all([resolve$1(client, artifact, from, python), resolve$1(client, artifact, to, python)], { concurrency: "unbounded" });
6645
6665
  const plans = {
6646
6666
  from: fromPlan,
6647
6667
  to: toPlan
@@ -6734,7 +6754,7 @@ const resolveDependencies = Effect.fn("npmDependencies.resolve")(function* (clie
6734
6754
  const outcomes = yield* Effect.forEach(changedNames, (dependency) => Effect.gen(function* () {
6735
6755
  if (!packageName.test(dependency)) return Result.fail("its name is not a valid registry package name");
6736
6756
  const side = (declared) => declared === void 0 ? Effect.undefined : resolveSide(client, host, dependency, declared);
6737
- const resolved = yield* Effect.result(Effect.all([side(before.get(dependency)), side(after.get(dependency))], { concurrency: 2 }));
6757
+ const resolved = yield* Effect.result(Effect.all([side(before.get(dependency)), side(after.get(dependency))], { concurrency: "unbounded" }));
6738
6758
  return Result.isFailure(resolved) ? Result.fail(resolved.failure.issue) : Result.succeed(resolved.success);
6739
6759
  }), { concurrency: 4 });
6740
6760
  for (const [index, dependency] of changedNames.entries()) {
@@ -6841,8 +6861,8 @@ const materializeDependencies = Effect.fn("npmDependencies.materialize")(functio
6841
6861
  issue: error instanceof Error ? error.message : String(error)
6842
6862
  })
6843
6863
  });
6844
- const sides = yield* Effect.forEach(dependencies.changed, (dependency) => Effect.all([fetchSide(client, dependency.from, path.join(workspace, files.dependenciesFrom, dependency.name)), fetchSide(client, dependency.to, path.join(workspace, files.dependenciesTo, dependency.name))], { concurrency: 2 }), { concurrency: 4 });
6845
- const summaries = yield* writeFileDiff(workspace, files.dependencyListFrom, files.dependencyListTo, record(dependencies, dependencies.changed.map((dependency, index) => ({
6864
+ const sides = yield* Effect.forEach(dependencies.changed, (dependency) => Effect.all([fetchSide(client, dependency.from, path.join(workspace, files.dependenciesFrom, dependency.name)), fetchSide(client, dependency.to, path.join(workspace, files.dependenciesTo, dependency.name))], { concurrency: "unbounded" }), { concurrency: 4 });
6865
+ const [summaries, trees] = yield* Effect.all([writeFileDiff(workspace, files.dependencyListFrom, files.dependencyListTo, record(dependencies, dependencies.changed.map((dependency, index) => ({
6846
6866
  name: dependency.name,
6847
6867
  ...dependency.from === void 0 ? {} : { resolved: dependency.from },
6848
6868
  ...sides[index]?.[0] === void 0 ? {} : { fetched: sides[index][0] }
@@ -6850,8 +6870,7 @@ const materializeDependencies = Effect.fn("npmDependencies.materialize")(functio
6850
6870
  name: dependency.name,
6851
6871
  ...dependency.to === void 0 ? {} : { resolved: dependency.to },
6852
6872
  ...sides[index]?.[1] === void 0 ? {} : { fetched: sides[index][1] }
6853
- }))));
6854
- const trees = yield* treeDiff(workspace, files.dependenciesFrom, files.dependenciesTo);
6873
+ })))), treeDiff(workspace, files.dependenciesFrom, files.dependenciesTo)], { concurrency: "unbounded" });
6855
6874
  const failed = dependencies.changed.filter((_, index) => (sides[index] ?? []).some((side) => side?.error !== void 0));
6856
6875
  const included = dependencies.changed.map((dependency) => `${dependency.name} ${dependency.from?.plan.version ?? "(new)"}${dependency.from?.lowest === true ? " (lowest of its range)" : ""} -> ${dependency.to?.plan.version ?? "(removed)"}${dependency.to?.bundled === true ? " (now a devDependency, so probably bundled into the package)" : ""}`);
6857
6876
  const noneIncluded = dependencies.omitted.length === 0 ? "No direct dependency's declared version changed." : "No changed direct dependency is compared.";
@@ -6884,10 +6903,12 @@ const materializeDependencies = Effect.fn("npmDependencies.materialize")(functio
6884
6903
  // src/audit/registry-evidence.ts
6885
6904
  const registryDetail = "Both published packages were downloaded and their checksums verified. File types and modes, and any native binaries, are summarised without running them.";
6886
6905
  const registryWorkspace = Effect.fn("evidence.registryWorkspace")(function* (client, workspace, identity, plans, npm, key) {
6887
- const [from, to] = yield* Effect.all([materialize$2(client, plans.from, path.join(workspace, files.from)), materialize$2(client, plans.to, path.join(workspace, files.to))], { concurrency: 2 });
6888
- const artifacts = yield* writeFileDiff(workspace, files.artifactFrom, files.artifactTo, manifestJson(from), manifestJson(to));
6889
- const trees = yield* treeDiff(workspace, files.from, files.to);
6890
- const binaries = yield* writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(from)), json(binarySummaries(to)));
6906
+ const [from, to] = yield* Effect.all([materialize$2(client, plans.from, path.join(workspace, files.from)), materialize$2(client, plans.to, path.join(workspace, files.to))], { concurrency: "unbounded" });
6907
+ const [artifacts, trees, binaries] = yield* Effect.all([
6908
+ writeFileDiff(workspace, files.artifactFrom, files.artifactTo, manifestJson(from), manifestJson(to)),
6909
+ treeDiff(workspace, files.from, files.to),
6910
+ writeFileDiff(workspace, files.binaryFrom, files.binaryTo, json(binarySummaries(from)), json(binarySummaries(to)))
6911
+ ], { concurrency: "unbounded" });
6891
6912
  const treeDetail = [registryDetail, partial("artifact", trees.omitted)].filter((sentence) => sentence !== "").join(" ");
6892
6913
  if (npm === void 0) return yield* write(workspace, identity, Buffer.concat([
6893
6914
  artifacts,
@@ -6921,7 +6942,7 @@ const npmExtras = Effect.fn("evidence.npmExtras")(function* (client, name, from,
6921
6942
  cpu: process.arch
6922
6943
  });
6923
6944
  const verifier = yield* Effect.cached(sigstoreVerifier);
6924
- const [fromSource, toSource] = yield* Effect.all([npmSource(client, name, from, fromManifest, verifier), npmSource(client, name, to, toManifest, verifier)], { concurrency: 2 });
6945
+ const [fromSource, toSource] = yield* Effect.all([npmSource(client, name, from, fromManifest, verifier), npmSource(client, name, to, toManifest, verifier)], { concurrency: "unbounded" });
6925
6946
  const { directory } = npmRepository(toManifest);
6926
6947
  return {
6927
6948
  dependencies,
@@ -6938,8 +6959,8 @@ const prepareRegistry = Effect.fn("evidence.prepareRegistry")(function* (client,
6938
6959
  const manifests = ecosystem === "npm" ? yield* Effect.all({
6939
6960
  from: npmVersion(client, artifact, from),
6940
6961
  to: npmVersion(client, artifact, to)
6941
- }, { concurrency: 2 }) : void 0;
6942
- const [fromPlan, toPlan] = yield* Effect.all(manifests === void 0 ? [resolve$3(client, ecosystem, artifact, from), resolve$3(client, ecosystem, artifact, to)] : [npmPlan(artifact, from, manifests.from), npmPlan(artifact, to, manifests.to)], { concurrency: 2 });
6962
+ }, { concurrency: "unbounded" }) : void 0;
6963
+ const [fromPlan, toPlan] = yield* Effect.all(manifests === void 0 ? [resolve$3(client, ecosystem, artifact, from), resolve$3(client, ecosystem, artifact, to)] : [npmPlan(artifact, from, manifests.from), npmPlan(artifact, to, manifests.to)], { concurrency: "unbounded" });
6943
6964
  const plans = {
6944
6965
  from: fromPlan,
6945
6966
  to: toPlan
@@ -7314,10 +7335,9 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
7314
7335
  }));
7315
7336
  const started = yield* Clock.currentTimeMillis;
7316
7337
  const base = path.join(root, "workspaces");
7317
- for (const name of yield* children(base)) {
7318
- if (name.endsWith(".lock")) continue;
7338
+ yield* Effect.forEach((yield* children(base)).filter((name) => !name.endsWith(".lock")), (name) => {
7319
7339
  const workspace = path.join(base, name);
7320
- yield* Effect.scoped(Effect.gen(function* () {
7340
+ return Effect.scoped(Effect.gen(function* () {
7321
7341
  if (!(yield* tryHold(workspace))) return;
7322
7342
  const prepared = yield* Effect.promise(async () => await stat(path.join(workspace, files.meta)).then((info) => info.mtimeMs, () => 0));
7323
7343
  if (started - prepared > Duration.toMillis(keptWorkspaces)) {
@@ -7325,9 +7345,15 @@ const layer$5 = (cacheDir) => Layer.effect(Audits, Effect.gen(function* () {
7325
7345
  return;
7326
7346
  }
7327
7347
  const entries = yield* Effect.promise(async () => await readdir(workspace, { withFileTypes: true }).catch(() => []));
7328
- for (const entry of entries) if (entry.isDirectory()) yield* discard(path.join(workspace, entry.name), name);
7348
+ yield* Effect.forEach(entries.filter((entry) => entry.isDirectory()), (entry) => discard(path.join(workspace, entry.name), name), {
7349
+ concurrency: "unbounded",
7350
+ discard: true
7351
+ });
7329
7352
  })).pipe(Effect.ignore);
7330
- }
7353
+ }, {
7354
+ concurrency: 8,
7355
+ discard: true
7356
+ });
7331
7357
  yield* Effect.forkScoped(Effect.promise(async () => {
7332
7358
  for (const name of await readdir(trash).catch(() => [])) await rm(path.join(trash, name), {
7333
7359
  recursive: true,
@@ -7544,12 +7570,15 @@ const workflowFiles = Effect.fn("workflowFiles")(function* (root) {
7544
7570
  for (const name of ["action.yml", "action.yaml"]) if (yield* present(path.join(dir, name))) return Option.some(path.join(dir, name));
7545
7571
  return Option.none();
7546
7572
  });
7547
- const workflows = yield* listed(path.join(".github", "workflows"), false);
7548
- const actions = yield* listed(path.join(".github", "actions"), true);
7573
+ const [workflows, actions, own] = yield* Effect.all([
7574
+ listed(path.join(".github", "workflows"), false),
7575
+ listed(path.join(".github", "actions"), true),
7576
+ actionFile("")
7577
+ ], { concurrency: "unbounded" });
7549
7578
  const pending = [
7550
7579
  ...workflows.filter((file) => /\.ya?ml$/u.test(file)),
7551
7580
  ...actions.filter((file) => /^action\.ya?ml$/u.test(path.basename(file))),
7552
- ...Option.toArray(yield* actionFile(""))
7581
+ ...Option.toArray(own)
7553
7582
  ];
7554
7583
  const seen = /* @__PURE__ */ new Set();
7555
7584
  const files = [];
@@ -7874,7 +7903,7 @@ const discover$4 = Effect.fn("GitHubActions.discover")(function* (dir) {
7874
7903
  ".github",
7875
7904
  "action.yml",
7876
7905
  "action.yaml"
7877
- ], exists)).length === 0) return [];
7906
+ ], exists, { concurrency: "unbounded" })).length === 0) return [];
7878
7907
  const origin = yield* exec.stdout({
7879
7908
  command: "git",
7880
7909
  args: [
@@ -7889,7 +7918,7 @@ const discover$4 = Effect.fn("GitHubActions.discover")(function* (dir) {
7889
7918
  });
7890
7919
  // src/process/on-path.ts
7891
7920
  const executable = (file) => Effect.promise(async () => await access(file, constants.X_OK).then(() => true, () => false));
7892
- const onPath = (command) => Effect.forEach((process.env["PATH"] ?? "").split(path.delimiter).filter((dir) => dir !== ""), (dir) => executable(path.join(dir, command))).pipe(Effect.map((found) => found.includes(true)));
7921
+ const onPath = (command) => Effect.forEach((process.env["PATH"] ?? "").split(path.delimiter).filter((dir) => dir !== ""), (dir) => executable(path.join(dir, command)), { concurrency: "unbounded" }).pipe(Effect.map((found) => found.includes(true)));
7893
7922
  // src/process/Sudo.ts
7894
7923
  var Sudo = class extends Context.Service()("upup/Sudo") {};
7895
7924
  const asRoot = (invocation) => [
@@ -8483,8 +8512,7 @@ const read = Effect.fn("bundles.read")(function* (bundle, arch) {
8483
8512
  const short = nonEmpty(info.value.CFBundleShortVersionString);
8484
8513
  const build = nonEmpty(info.value.CFBundleVersion);
8485
8514
  const executable = nonEmpty(info.value.CFBundleExecutable);
8486
- const sparkle = yield* sparkleKeysOf(bundle, info.value);
8487
- const source = yield* sourceOf(bundle, bundleId, nonEmpty(info.value.SUFeedURL), arch);
8515
+ const [sparkle, source] = yield* Effect.all([sparkleKeysOf(bundle, info.value), sourceOf(bundle, bundleId, nonEmpty(info.value.SUFeedURL), arch)], { concurrency: "unbounded" });
8488
8516
  return Option.some({
8489
8517
  path: bundle,
8490
8518
  name: path.basename(bundle, ".app"),
@@ -8497,23 +8525,25 @@ const read = Effect.fn("bundles.read")(function* (bundle, arch) {
8497
8525
  ...plist === void 0 ? {} : { plist }
8498
8526
  });
8499
8527
  });
8500
- const walk = Effect.fn("bundles.walk")(function* (roots, wanted) {
8528
+ const isApp = (entry) => entry.endsWith(".app");
8529
+ const isLeftover = (entry) => entry.endsWith(".app.upup-old");
8530
+ const wanted$1 = (entry) => isApp(entry) || isLeftover(entry);
8531
+ const walk = Effect.fn("bundles.walk")(function* (roots) {
8501
8532
  const fs = yield* FileSystem.FileSystem;
8502
8533
  const entries = (dir) => fs.readDirectory(dir).pipe(Effect.orElseSucceed(() => []), Effect.map((names) => names.toSorted((left, right) => left.localeCompare(right)).map((name) => path.join(dir, name))));
8503
8534
  const isLink = (entry) => fs.readLink(entry).pipe(Effect.isSuccess);
8504
8535
  const isDirectory = (entry) => fs.stat(entry).pipe(Effect.map((info) => info.type === "Directory"), Effect.orElseSucceed(() => false));
8505
- const found = [];
8506
- for (const root of roots) for (const entry of yield* entries(root)) {
8507
- if (yield* isLink(entry)) continue;
8508
- if (wanted(entry)) found.push(entry);
8509
- else if (!/\.(?:app|localized|upup-old|upup-new)$/u.test(entry) && (yield* isDirectory(entry))) {
8510
- for (const nested of yield* entries(entry)) if (wanted(nested) && !(yield* isLink(nested))) found.push(nested);
8511
- }
8512
- }
8513
- return found;
8536
+ const nestedIn = (folder) => entries(folder).pipe(Effect.flatMap((listed) => Effect.filter(listed.filter(wanted$1), (nested) => Effect.map(isLink(nested), (link) => !link), { concurrency: "unbounded" })));
8537
+ const walked = (yield* Effect.forEach(roots, (root) => entries(root).pipe(Effect.flatMap((listed) => Effect.forEach(listed, (entry) => Effect.gen(function* () {
8538
+ if (yield* isLink(entry)) return [];
8539
+ if (wanted$1(entry)) return [entry];
8540
+ return !/\.(?:app|localized|upup-old|upup-new)$/u.test(entry) && (yield* isDirectory(entry)) ? yield* nestedIn(entry) : [];
8541
+ }), { concurrency: "unbounded" })), Effect.map((listed) => listed.flat())), { concurrency: "unbounded" })).flat();
8542
+ return {
8543
+ apps: walked.filter(isApp),
8544
+ leftovers: walked.filter(isLeftover)
8545
+ };
8514
8546
  });
8515
- const paths = (roots) => walk(roots, (entry) => entry.endsWith(".app"));
8516
- const leftovers = (roots) => walk(roots, (entry) => entry.endsWith(".app.upup-old"));
8517
8547
  // src/apps/running.ts
8518
8548
  const command$4 = (name, args) => ({
8519
8549
  command: name,
@@ -8576,7 +8606,7 @@ const command$3 = (name, args) => ({
8576
8606
  });
8577
8607
  const host = Effect.gen(function* () {
8578
8608
  const exec = yield* Exec;
8579
- const [arm64, os] = yield* Effect.all([exec.run(command$3("sysctl", ["-n", "hw.optional.arm64"])).pipe(Effect.map((output) => output.exitCode === 0 && output.stdout.trim() === "1"), Effect.orElseSucceed(() => false)), exec.stdout(command$3("sw_vers", ["-productVersion"])).pipe(Effect.map((text) => text.trim()))], { concurrency: 2 });
8609
+ const [arm64, os] = yield* Effect.all([exec.run(command$3("sysctl", ["-n", "hw.optional.arm64"])).pipe(Effect.map((output) => output.exitCode === 0 && output.stdout.trim() === "1"), Effect.orElseSucceed(() => false)), exec.stdout(command$3("sw_vers", ["-productVersion"])).pipe(Effect.map((text) => text.trim()))], { concurrency: "unbounded" });
8580
8610
  return {
8581
8611
  arch: arm64 ? "arm64" : "x86_64",
8582
8612
  os
@@ -8654,7 +8684,7 @@ const stage = Effect.fn("install.stage")(function* (client, wanted) {
8654
8684
  const found = (yield* Effect.forEach(candidates, (candidate) => readInfo(candidate).pipe(Effect.map((info) => ({
8655
8685
  path: candidate,
8656
8686
  info
8657
- }))))).find(({ info }) => Option.isSome(info) && info.value.CFBundleIdentifier === wanted.bundleId);
8687
+ }))), { concurrency: 4 })).find(({ info }) => Option.isSome(info) && info.value.CFBundleIdentifier === wanted.bundleId);
8658
8688
  if (found === void 0 || Option.isNone(found.info)) return yield* refused(`its download holds no app with the bundle ID ${wanted.bundleId}`);
8659
8689
  const app = found.path;
8660
8690
  const info = found.info.value;
@@ -8673,7 +8703,7 @@ const stage = Effect.fn("install.stage")(function* (client, wanted) {
8673
8703
  ])).pipe(Effect.mapError((error) => refused(`codesign failed: ${error.output.trim()}`)), Effect.flatMap((output) => {
8674
8704
  const hash = /^CDHash=(?<hash>[0-9a-f]+)$/mu.exec(output.stderr)?.groups?.["hash"];
8675
8705
  return hash === void 0 ? Effect.fail(unsigned(output.stderr.trim())) : Effect.succeed(hash);
8676
- }))).pipe(Effect.map((hashes) => `${requirement(wanted.bundleId, wanted.team)} and info [CFBundleShortVersionString] = "${wanted.version.replaceAll(/["\\]/gu, "\\$&")}" and (${hashes.map((hash) => `cdhash H"${hash}"`).join(" or ")})`));
8706
+ })), { concurrency: 2 }).pipe(Effect.map((hashes) => `${requirement(wanted.bundleId, wanted.team)} and info [CFBundleShortVersionString] = "${wanted.version.replaceAll(/["\\]/gu, "\\$&")}" and (${hashes.map((hash) => `cdhash H"${hash}"`).join(" or ")})`));
8677
8707
  const signed = yield* exec.run(command$2("codesign", [
8678
8708
  "--verify",
8679
8709
  "--deep",
@@ -8726,19 +8756,11 @@ const Manifest$2 = Schema.fromJsonString(Schema.Struct({
8726
8756
  }));
8727
8757
  const zipName = "upup-sparkle.zip";
8728
8758
  const manifestName = "upup-sparkle.json";
8729
- const seaKeys = {
8730
- zip: `sparkle/${zipName}`,
8731
- manifest: `sparkle/${manifestName}`
8732
- };
8733
8759
  const decode = (text, zip) => Schema.decodeEffect(Manifest$2)(text).pipe(Effect.map((manifest) => ({
8734
8760
  zip,
8735
8761
  ...manifest
8736
8762
  })), Effect.option);
8737
8763
  const folder = () => {
8738
- if (isSea()) {
8739
- const assets = process.env["OTUI_ASSET_ROOT"];
8740
- return assets === void 0 ? void 0 : path.join(assets, path.dirname(seaKeys.zip));
8741
- }
8742
8764
  const packageJson = findPackageJSON(import.meta.url);
8743
8765
  return packageJson === void 0 ? void 0 : path.join(path.dirname(packageJson), "native", "dist");
8744
8766
  };
@@ -8820,9 +8842,16 @@ ready() {
8820
8842
  return 1
8821
8843
  fi
8822
8844
  }
8823
- # A copy of what upup handed over, where only this user can write; a failure is step $1's.
8845
+ # A copy of what upup handed over, where only this user can write; a failure is step $1's. Others
8846
+ # may also read a shared one ($2): as root, Sparkle starts its progress agent from upup-sparkle's
8847
+ # framework as the user, so it goes in /var/tmp, whose sticky bit keeps others from moving it. An
8848
+ # app's copy stays private, since its owner gets it after it is checked.
8824
8849
  secure() {
8825
- private=$(mktemp -d 2>"$log") || { private=; fail "$1"; return 1; }
8850
+ if [ "$mode" = root ] && [ "$2" = shared ]; then
8851
+ private=$(mktemp -d /var/tmp/upup.XXXXXX 2>"$log") && chmod 755 "$private" 2>"$log" || { fail "$1"; return 1; }
8852
+ else
8853
+ private=$(mktemp -d 2>"$log") || { fail "$1"; return 1; }
8854
+ fi
8826
8855
  payload="$private/$(basename "$source")"
8827
8856
  "$ditto" "$source" "$payload" 2>"$log" || { fail "$1"; return 1; }
8828
8857
  }
@@ -8836,7 +8865,7 @@ app() {
8836
8865
  if [ -e "$old" ] && [ ! -e "$dest" ]; then recover; return; fi
8837
8866
  rm -rf "$old" "$new" 2>"$log" || { fail cleanup; return; }
8838
8867
  if [ "$mode" = root ]; then
8839
- secure copy || return
8868
+ secure copy private || return
8840
8869
  "$codesign" --verify --deep --strict -R "$check" "$payload" 2>"$log" || { fail recheck; return; }
8841
8870
  owner=$("$stat" -f %u:%g "$dest" 2>"$log") && "$chown" -R "$owner" "$payload" 2>"$log" || { fail copy; return; }
8842
8871
  staged=$payload
@@ -8866,7 +8895,7 @@ app() {
8866
8895
  # upup-sparkle's exit status: 0 installed, 2 nothing to install, 3 Sparkle would install another
8867
8896
  # build, 4 the app is open; its last line on standard error says why.
8868
8897
  sparkle() {
8869
- secure helper || return
8898
+ secure helper shared || return
8870
8899
  sum=$("$shasum" -a 256 "$payload" 2>"$log") || { fail helper; return; }
8871
8900
  [ "\${sum%% *}" = "$check" ] || { echo "its sha256 is \${sum%% *}, not $check" >"$log"; fail helper; return; }
8872
8901
  "$ditto" -x -k "$payload" "$private" 2>"$log" || { fail helper; return; }
@@ -9156,16 +9185,27 @@ const makeWith = (options) => Effect.gen(function* () {
9156
9185
  }
9157
9186
  };
9158
9187
  });
9188
+ const leftoverNotice = (old) => {
9189
+ const app = old.slice(0, -9);
9190
+ return fs.exists(app).pipe(Effect.orElseSucceed(() => true), Effect.map((present) => ({ message: present ? `${old} is the old copy of ${path.basename(app)} that an update left behind; move it to the Trash` : `${old} is ${path.basename(app)} from before an update that did not finish; rename it back to ${path.basename(app)}` })));
9191
+ };
9192
+ const scan = Effect.gen(function* () {
9193
+ const [here, walked] = yield* Effect.all([host, walk(options.roots)], { concurrency: "unbounded" });
9194
+ const [bundles, left] = yield* Effect.all([Effect.forEach(walked.apps, (app) => read(app, here.arch), { concurrency: inFlight }), Effect.forEach(walked.leftovers, leftoverNotice, { concurrency: "unbounded" })], { concurrency: "unbounded" });
9195
+ return {
9196
+ here,
9197
+ found: bundles.flatMap((bundle) => Option.toArray(bundle)),
9198
+ left
9199
+ };
9200
+ });
9159
9201
  const list = Effect.gen(function* () {
9160
- const owners = yield* Effect.result(casks);
9202
+ const [owners, { here, found, left }] = yield* Effect.all([Effect.result(casks), scan], { concurrency: "unbounded" });
9161
9203
  if (Result.isFailure(owners)) return {
9162
9204
  packages: [],
9163
9205
  notices: [{ message: `upup lists no apps while it cannot read which apps Homebrew installed: ${describeError(owners.failure)}` }]
9164
9206
  };
9165
- const here = yield* host;
9166
9207
  const locale = yield* Effect.cached(country);
9167
9208
  const caskOf = new Map(owners.success.flatMap((cask) => caskApps(cask).map((app) => [app, cask])));
9168
- const found = (yield* Effect.forEach(yield* paths(options.roots), (app) => read(app, here.arch), { concurrency: inFlight })).flatMap((bundle) => Option.toArray(bundle));
9169
9209
  const ids = /* @__PURE__ */ new Set();
9170
9210
  const kept = found.filter((bundle) => {
9171
9211
  const cask = caskOf.get(path.basename(bundle.path));
@@ -9193,13 +9233,9 @@ const makeWith = (options) => Effect.gen(function* () {
9193
9233
  here,
9194
9234
  rows: new Map(all.map((row) => [row.pkg.id, row.listed]))
9195
9235
  });
9196
- const leftovers$1 = yield* Effect.forEach(yield* leftovers(options.roots), (old) => {
9197
- const app = old.slice(0, -9);
9198
- return fs.exists(app).pipe(Effect.orElseSucceed(() => true), Effect.map((present) => ({ message: present ? `${old} is the old copy of ${path.basename(app)} that an update left behind; move it to the Trash` : `${old} is ${path.basename(app)} from before an update that did not finish; rename it back to ${path.basename(app)}` })));
9199
- });
9200
9236
  return {
9201
9237
  packages: all.map((row) => row.pkg),
9202
- notices: [...all.flatMap((row) => row.notice), ...leftovers$1]
9238
+ notices: [...all.flatMap((row) => row.notice), ...left]
9203
9239
  };
9204
9240
  }).pipe(Effect.withSpan("Apps.list"), provide);
9205
9241
  const observe = Effect.fn("Apps.observe")(function* (pkg) {
@@ -9234,7 +9270,7 @@ const makeWith = (options) => Effect.gen(function* () {
9234
9270
  const ids = yield* Effect.forEach(paths, (app) => readInfo(app).pipe(Effect.flatMap((info) => Option.match(info, {
9235
9271
  onNone: () => Effect.fail(new Unsupported({ reason: `upup could not read ${app}` })),
9236
9272
  onSome: (found) => Effect.succeed(found.CFBundleIdentifier)
9237
- }))));
9273
+ }))), { concurrency: inFlight });
9238
9274
  const found = {
9239
9275
  paths,
9240
9276
  ids: new Set(ids)
@@ -9515,7 +9551,7 @@ const nestedDirs = Effect.fn("nestedDirs")(function* (dir, names) {
9515
9551
  args,
9516
9552
  cwd: dir
9517
9553
  }).pipe(Effect.orElseSucceed(() => ""));
9518
- const [prefix, listed] = yield* Effect.all([git("rev-parse", "--show-prefix"), git("ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", ...names.map((name) => `:(glob)**/${name}`))], { concurrency: 2 });
9554
+ const [prefix, listed] = yield* Effect.all([git("rev-parse", "--show-prefix"), git("ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", ...names.map((name) => `:(glob)**/${name}`))], { concurrency: "unbounded" });
9519
9555
  const files = listed.split("\0").filter((file) => {
9520
9556
  const folders = file.split("/").slice(0, -1);
9521
9557
  return folders.length > 0 && !folders.includes("node_modules") && !(path.basename(file) === "go.mod" && ignoredByGo(folders));
@@ -9542,8 +9578,7 @@ const failing = (name, error) => ({
9542
9578
  observe: () => Effect.succeedNone
9543
9579
  });
9544
9580
  const locateAll = Effect.fn("locateAll")(function* (dir, nested, manifest, locate) {
9545
- const own = yield* locate(dir);
9546
- const below = yield* Effect.forEach(nested, (from) => Effect.map(Effect.result(locate(from)), (result) => [from, result]), { concurrency: 8 });
9581
+ const [own, below] = yield* Effect.all([locate(dir), Effect.forEach(nested, (from) => Effect.map(Effect.result(locate(from)), (result) => [from, result]), { concurrency: 8 })], { concurrency: "unbounded" });
9547
9582
  const found = /* @__PURE__ */ new Map();
9548
9583
  const claimed = /* @__PURE__ */ new Map();
9549
9584
  const failed = [];
@@ -9706,7 +9741,7 @@ const make$9 = (root, place = "") => Effect.gen(function* () {
9706
9741
  const entries = (manifest) => manifestOf(manifest).pipe(Effect.map((parsed) => entriesOf(manifest, parsed)));
9707
9742
  const workspace = Effect.gen(function* () {
9708
9743
  const resolved = resolvedByMember(root, yield* metadata);
9709
- const manifests = yield* Effect.forEach(/* @__PURE__ */ new Set(["Cargo.toml", ...resolved.keys()]), (manifest) => manifestOf(manifest).pipe(Effect.map((parsed) => [manifest, parsed])));
9744
+ const manifests = yield* Effect.forEach(/* @__PURE__ */ new Set(["Cargo.toml", ...resolved.keys()]), (manifest) => manifestOf(manifest).pipe(Effect.map((parsed) => [manifest, parsed])), { concurrency: 8 });
9710
9745
  const inheritors = (key) => manifests.flatMap(([manifest, parsed]) => resolved.has(manifest) && inheritedKeys(parsed).includes(key) ? [manifest] : []);
9711
9746
  return {
9712
9747
  resolved,
@@ -10011,9 +10046,11 @@ const make$8 = Effect.gen(function* () {
10011
10046
  });
10012
10047
  const isPlainExecutable = Effect.fn("GoInstall.isPlainExecutable")(function* (dir, file) {
10013
10048
  const binary = path.join(dir, file);
10014
- const info = yield* fs.stat(binary).pipe(Effect.mapError(fileFailed("stat", binary)));
10015
- const real = yield* fs.realPath(binary).pipe(Effect.mapError(fileFailed("resolve", binary)));
10016
- const realDir = yield* fs.realPath(dir).pipe(Effect.mapError(fileFailed("resolve", dir)));
10049
+ const [info, real, realDir] = yield* Effect.all([
10050
+ fs.stat(binary).pipe(Effect.mapError(fileFailed("stat", binary))),
10051
+ fs.realPath(binary).pipe(Effect.mapError(fileFailed("resolve", binary))),
10052
+ fs.realPath(dir).pipe(Effect.mapError(fileFailed("resolve", dir)))
10053
+ ], { concurrency: "unbounded" });
10017
10054
  return info.type === "File" && (info.mode & 73) !== 0 && real === path.join(realDir, file);
10018
10055
  });
10019
10056
  const latest = Effect.fn("GoInstall.latest")(function* (modules) {
@@ -10172,8 +10209,7 @@ const make$7 = (root, moduleDir, place = "", local = /* @__PURE__ */ new Set())
10172
10209
  ]);
10173
10210
  const origin = exec.stdout(env).pipe(Effect.flatMap(decodeGoJson(GoProxyEnv, commandLine(env))), Effect.map(withGoOrigin));
10174
10211
  const list = Effect.gen(function* () {
10175
- const direct = yield* requirements;
10176
- const located = yield* origin;
10212
+ const [direct, located] = yield* Effect.all([requirements, origin], { concurrency: "unbounded" });
10177
10213
  const entries = yield* selected(direct.map((requirement) => requirement.Path), true);
10178
10214
  const notices = [];
10179
10215
  return {
@@ -10235,17 +10271,17 @@ const locate$1 = Effect.fn("GoModule.locate")(function* (dir) {
10235
10271
  const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
10236
10272
  const exec = yield* Exec;
10237
10273
  const { found, failed } = yield* locateAll(dir, nested, "go.mod", locate$1);
10238
- const failedWorks = [];
10239
- const listed = /* @__PURE__ */ new Set();
10240
- const modules = yield* Effect.forEach(found, ({ root, work, claimed }) => Effect.gen(function* () {
10241
- if (!work) {
10242
- listed.add(root);
10243
- return [{
10274
+ const works = yield* Effect.forEach(found, ({ root, work, claimed }) => Effect.gen(function* () {
10275
+ if (!work) return {
10276
+ modules: [{
10244
10277
  root,
10245
10278
  moduleDir: root,
10246
10279
  local: /* @__PURE__ */ new Set()
10247
- }];
10248
- }
10280
+ }],
10281
+ failed: [],
10282
+ covered: [root]
10283
+ };
10284
+ const covered = [];
10249
10285
  const place = placeOf$1(dir, root);
10250
10286
  const scanned = yield* Effect.gen(function* () {
10251
10287
  const edit = {
@@ -10259,7 +10295,7 @@ const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
10259
10295
  };
10260
10296
  const file = yield* exec.stdout(edit).pipe(Effect.flatMap(decodeGoJson(WorkFile, commandLine(edit))));
10261
10297
  const used = (file.Use ?? []).map((use) => path.resolve(root, use.DiskPath));
10262
- for (const moduleDir of used) listed.add(moduleDir);
10298
+ covered.push(...used);
10263
10299
  const paths = yield* Effect.forEach(used, (moduleDir) => Effect.gen(function* () {
10264
10300
  const mod = yield* readModFile(exec, moduleDir);
10265
10301
  if (mod.Module === void 0) return yield* new OutputMalformed({
@@ -10275,20 +10311,27 @@ const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
10275
10311
  local
10276
10312
  })).filter(({ moduleDir }) => place === "" || placeOf$1(dir, moduleDir) !== "");
10277
10313
  }).pipe(Effect.result);
10278
- if (Result.isSuccess(scanned)) return scanned.success;
10279
- for (const moduleDir of claimed) listed.add(moduleDir);
10280
- failedWorks.push(failing(path.join(place, "go.work"), scanned.failure));
10281
- return [];
10282
- }));
10314
+ if (Result.isSuccess(scanned)) return {
10315
+ modules: scanned.success,
10316
+ failed: [],
10317
+ covered
10318
+ };
10319
+ return {
10320
+ modules: [],
10321
+ failed: [failing(path.join(place, "go.work"), scanned.failure)],
10322
+ covered: [...covered, ...claimed]
10323
+ };
10324
+ }), { concurrency: 4 });
10325
+ const listed = new Set(works.flatMap((work) => work.covered));
10283
10326
  const outside = nested.flatMap((moduleDir) => listed.has(moduleDir) ? [] : [{
10284
10327
  root: moduleDir,
10285
10328
  moduleDir,
10286
10329
  local: /* @__PURE__ */ new Set()
10287
10330
  }]);
10288
- const providers = yield* Effect.forEach([...modules.flat(), ...outside], ({ root, moduleDir, local }) => make$7(root, moduleDir, placeOf$1(dir, root), local));
10331
+ const providers = yield* Effect.forEach([...works.flatMap(({ modules }) => modules), ...outside], ({ root, moduleDir, local }) => make$7(root, moduleDir, placeOf$1(dir, root), local));
10289
10332
  return [
10290
10333
  ...failed,
10291
- ...failedWorks,
10334
+ ...works.flatMap((work) => work.failed),
10292
10335
  ...providers
10293
10336
  ];
10294
10337
  });
@@ -10296,24 +10339,23 @@ const discover$2 = Effect.fn("GoModule.discover")(function* (dir, nested = []) {
10296
10339
  var ProviderSource = class extends Context.Service()("upup/ProviderSource") {};
10297
10340
  // src/node/release-history.ts
10298
10341
  const minutesPerDay = 1440;
10299
- const firstPnpmMajorWithDefaultReleaseAge = 11;
10300
10342
  const gateSettings = {
10301
10343
  pnpm: {
10302
10344
  age: "minimumReleaseAge",
10303
10345
  exclude: "minimumReleaseAgeExclude",
10304
10346
  unit: 1,
10305
- unset: (version) => (semver.coerce(version)?.major ?? 0) >= firstPnpmMajorWithDefaultReleaseAge ? minutesPerDay : 0
10347
+ unset: minutesPerDay
10306
10348
  },
10307
10349
  npm: {
10308
10350
  age: "min-release-age",
10309
10351
  exclude: "min-release-age-exclude",
10310
10352
  unit: minutesPerDay,
10311
- unset: () => 0
10353
+ unset: 0
10312
10354
  }
10313
10355
  };
10314
- const releaseGate = (manager, version, config) => {
10356
+ const releaseGate = (manager, config) => {
10315
10357
  const settings = gateSettings[manager];
10316
- const minutes = Number(config[settings.age] ?? settings.unset(version)) * settings.unit;
10358
+ const minutes = Number(config[settings.age] ?? settings.unset) * settings.unit;
10317
10359
  return {
10318
10360
  minutes: Number.isFinite(minutes) && minutes > 0 ? minutes : 0,
10319
10361
  exclude: [config[settings.exclude] ?? []].flat().filter((pattern) => typeof pattern === "string")
@@ -10399,8 +10441,7 @@ const releaseOffers = Effect.fn("releaseOffers")(function* (pins, manager, run,
10399
10441
  const reads = yield* Effect.result(Effect.forEach(artifacts, read, { concurrency: 8 }));
10400
10442
  const histories = new Map(Result.isSuccess(reads) ? reads.success : []);
10401
10443
  const notices = Result.isFailure(reads) ? [{ message: `release histories could not be read, so upup offers nothing: ${describeError(reads.failure)}` }] : [];
10402
- const version = manager === "pnpm" && histories.size > 0 ? yield* exec.stdout(run(["--version"])) : "";
10403
- const gate = releaseGate(manager, version.trim(), config);
10444
+ const gate = releaseGate(manager, config);
10404
10445
  const offer = (pin) => {
10405
10446
  const history = histories.get(pin.artifact);
10406
10447
  if (history === void 0) return Result.succeed(void 0);
@@ -10511,7 +10552,7 @@ const makeGlobal = (spec) => Effect.gen(function* () {
10511
10552
  installed,
10512
10553
  latest,
10513
10554
  readNpmConfig(spec.config, "/").pipe(Effect.provideService(Exec, exec))
10514
- ], { concurrency: 3 });
10555
+ ], { concurrency: "unbounded" });
10515
10556
  const { offer, notices: unread } = yield* releaseOffers(packages.filter((pkg) => isPrerelease(pkg.current)), spec.config, (args) => ({
10516
10557
  command: spec.config,
10517
10558
  args,
@@ -10742,9 +10783,10 @@ const scan = Effect.fn("NodePins.scan")(function* (root, dir, nested) {
10742
10783
  const fs = yield* FileSystem.FileSystem;
10743
10784
  const read = (file) => readText(path.join(root, file));
10744
10785
  const exists = (file) => fs.exists(path.join(root, file)).pipe(Effect.mapError(fileFailed("stat", path.join(root, file))));
10745
- const steps = (yield* workflowFiles(root)).flatMap(({ file, text }) => stepPins(file, text) ?? []);
10746
- const versioned = yield* Effect.filter(yield* versionFilesOf(root, dir, nested), exists);
10747
- const files = yield* Effect.forEach(versioned.toSorted(), (file) => Effect.map(read(file), (text) => filePin(file, text)));
10786
+ const [workflows, listed] = yield* Effect.all([workflowFiles(root), versionFilesOf(root, dir, nested)], { concurrency: "unbounded" });
10787
+ const steps = workflows.flatMap(({ file, text }) => stepPins(file, text) ?? []);
10788
+ const versioned = yield* Effect.filter(listed, exists, { concurrency: "unbounded" });
10789
+ const files = yield* Effect.forEach(versioned.toSorted(), (file) => Effect.map(read(file), (text) => filePin(file, text)), { concurrency: 8 });
10748
10790
  return [...steps, ...files.flat()];
10749
10791
  });
10750
10792
  const make$6 = (root, dir = root, nested = []) => Effect.gen(function* () {
@@ -11007,26 +11049,31 @@ const make$5 = (root, manager, place = "", claimed = []) => Effect.gen(function*
11007
11049
  const unlocked = claimed.filter((dir) => !lockedDirs.has(path.normalize(dir))).toSorted((a, b) => a.localeCompare(b));
11008
11050
  if (unlocked.length > 0) notices.push({ message: `not listed: ${unlocked.join(", ")} (not in ${lockfile})` });
11009
11051
  const catalogLocked = /* @__PURE__ */ new Map();
11010
- for (const member of members.toSorted((a, b) => a.localeCompare(b))) {
11052
+ const memberManifests = yield* Effect.forEach(members.toSorted((a, b) => a.localeCompare(b)), (member) => {
11011
11053
  const memberDir = member === "." ? "" : member;
11012
11054
  const manifest = path.join(memberDir, "package.json");
11013
- const fields = yield* readJson(Manifest, path.join(root, manifest));
11014
- for (const section of sections) for (const [name, spec] of Object.entries(fields[section] ?? {})) {
11015
- const resolved = Option.match(pnpm, {
11016
- onSome: (lock) => resolvedVersion(lock.importers?.[member]?.[section]?.[name]?.version),
11017
- onNone: () => Option.match(npm, {
11018
- onSome: (lock) => lock.packages[path.join(memberDir, "node_modules", name)]?.version ?? lock.packages[path.join("node_modules", name)]?.version,
11019
- onNone: () => void 0
11020
- })
11021
- });
11022
- if (spec.startsWith("catalog:")) {
11023
- const catalog = spec.slice(8) || "default";
11024
- const locked = catalogLocked.get(catalog) ?? /* @__PURE__ */ new Map();
11025
- if (resolved !== void 0 && !locked.has(name)) catalogLocked.set(catalog, locked.set(name, resolved));
11026
- continue;
11027
- }
11028
- add(manifest, section, [section, name], name, spec, resolved);
11055
+ return Effect.map(readJson(Manifest, path.join(root, manifest)), (fields) => ({
11056
+ member,
11057
+ memberDir,
11058
+ manifest,
11059
+ fields
11060
+ }));
11061
+ }, { concurrency: 8 });
11062
+ for (const { member, memberDir, manifest, fields } of memberManifests) for (const section of sections) for (const [name, spec] of Object.entries(fields[section] ?? {})) {
11063
+ const resolved = Option.match(pnpm, {
11064
+ onSome: (lock) => resolvedVersion(lock.importers?.[member]?.[section]?.[name]?.version),
11065
+ onNone: () => Option.match(npm, {
11066
+ onSome: (lock) => lock.packages[path.join(memberDir, "node_modules", name)]?.version ?? lock.packages[path.join("node_modules", name)]?.version,
11067
+ onNone: () => void 0
11068
+ })
11069
+ });
11070
+ if (spec.startsWith("catalog:")) {
11071
+ const catalog = spec.slice(8) || "default";
11072
+ const locked = catalogLocked.get(catalog) ?? /* @__PURE__ */ new Map();
11073
+ if (resolved !== void 0 && !locked.has(name)) catalogLocked.set(catalog, locked.set(name, resolved));
11074
+ continue;
11029
11075
  }
11076
+ add(manifest, section, [section, name], name, spec, resolved);
11030
11077
  }
11031
11078
  if (Option.isSome(pnpm) && (yield* exists(path.join(root, "pnpm-workspace.yaml")))) {
11032
11079
  const workspacePath = path.join(root, "pnpm-workspace.yaml");
@@ -11096,7 +11143,7 @@ const make$5 = (root, manager, place = "", claimed = []) => Effect.gen(function*
11096
11143
  };
11097
11144
  }).pipe(Effect.provideService(FileSystem.FileSystem, fs));
11098
11145
  const list = Effect.gen(function* () {
11099
- const [{ declared, notices }, config] = yield* Effect.all([declarations, readNpmConfig(manager, root).pipe(Effect.provideService(Exec, exec))], { concurrency: 2 });
11146
+ const [{ declared, notices }, config] = yield* Effect.all([declarations, readNpmConfig(manager, root).pipe(Effect.provideService(Exec, exec))], { concurrency: "unbounded" });
11100
11147
  const origin = withNpmOrigin(npmRegistries(config));
11101
11148
  const { offer, notices: unread } = yield* releaseOffers(declared.flatMap((entry) => entry.held === true ? [] : [entry.pkg]), manager, run, config).pipe(Effect.provideService(Exec, exec));
11102
11149
  return {
@@ -11302,7 +11349,7 @@ const discover = Effect.fn("NodeProject.discover")(function* (dir, nested = [])
11302
11349
  const installed = yield* fs.exists(lockfile).pipe(Effect.mapError(fileFailed("stat", lockfile)));
11303
11350
  if (place !== "" && !installed) unlisted.push(`${place} (no ${lockfiles[manager]} yet)`);
11304
11351
  else {
11305
- const manifests = yield* Effect.filter(claimed, (from) => fs.exists(path.join(from, "package.json")).pipe(Effect.mapError(fileFailed("stat", from))));
11352
+ const manifests = yield* Effect.filter(claimed, (from) => fs.exists(path.join(from, "package.json")).pipe(Effect.mapError(fileFailed("stat", from))), { concurrency: "unbounded" });
11306
11353
  providers.push(yield* make$5(root, manager, place, manifests.map((from) => path.relative(root, from))));
11307
11354
  }
11308
11355
  }
@@ -11401,10 +11448,13 @@ const make$4 = Effect.gen(function* () {
11401
11448
  });
11402
11449
  const list = Effect.gen(function* () {
11403
11450
  const found = yield* configured;
11451
+ const offered = yield* Effect.forEach(found.packages, (pkg) => Effect.map(Effect.result(offer(pkg)), (target) => ({
11452
+ pkg,
11453
+ target
11454
+ })), { concurrency: 4 });
11404
11455
  const notices = [...found.notices];
11405
11456
  return {
11406
- packages: yield* Effect.forEach(found.packages, (pkg) => Effect.gen(function* () {
11407
- const target = yield* Effect.result(offer(pkg));
11457
+ packages: offered.map(({ pkg, target }) => {
11408
11458
  if (Result.isFailure(target)) {
11409
11459
  notices.push({
11410
11460
  rowKey: rowKey(pkg),
@@ -11413,7 +11463,7 @@ const make$4 = Effect.gen(function* () {
11413
11463
  return pkg;
11414
11464
  }
11415
11465
  return target.success === void 0 ? pkg : withTarget(pkg, target.success);
11416
- })),
11466
+ }),
11417
11467
  notices
11418
11468
  };
11419
11469
  }).pipe(Effect.withSpan("VpEnv.list"));
@@ -11545,7 +11595,7 @@ const make$2 = Effect.gen(function* () {
11545
11595
  exec.stdout(command$1("apt", ["list", "--upgradable"])).pipe(Effect.map(parseUpgradable)),
11546
11596
  exec.stdout(command$1("apt-mark", ["showhold"])).pipe(Effect.map((text) => new Set(text.split("\n").filter((line) => line !== "")))),
11547
11597
  restart
11548
- ], { concurrency: 4 });
11598
+ ], { concurrency: "unbounded" });
11549
11599
  const packages = upgradable.map((entry) => {
11550
11600
  const pkg = packageOf(entry, arch);
11551
11601
  return holds.has(entry.name) || holds.has(pkg.id) ? pkg : withTarget(pkg, entry.version);
@@ -11690,7 +11740,7 @@ const make$1 = Effect.gen(function* () {
11690
11740
  running,
11691
11741
  scan(args),
11692
11742
  Ref.get(installed)
11693
- ], { concurrency: 2 });
11743
+ ], { concurrency: "unbounded" });
11694
11744
  return {
11695
11745
  packages: packagesOf$1(version, offers.filter((offer) => !done.has(offer.label))),
11696
11746
  done
@@ -11775,7 +11825,7 @@ const make = Effect.gen(function* () {
11775
11825
  "list",
11776
11826
  "--outdated",
11777
11827
  "--show-python"
11778
- ])).pipe(Effect.map(parseTools))], { concurrency: 2 });
11828
+ ])).pipe(Effect.map(parseTools))], { concurrency: "unbounded" });
11779
11829
  const targets = new Map(outdated.flatMap((tool) => tool.fromPyPI && tool.latest !== void 0 ? [[tool.pkg.id, tool.latest]] : []));
11780
11830
  const index = privatePypiIndex();
11781
11831
  return {
@@ -11824,8 +11874,8 @@ const system$1 = [
11824
11874
  ["go", make$8],
11825
11875
  ["uv", make]
11826
11876
  ];
11827
- const available = (entries) => Effect.filter([...new Set(entries.map(([command]) => command))], onPath).pipe(Effect.map((found) => entries.filter(([command]) => found.includes(command))));
11828
- const systemProviders = available(system$1).pipe(Effect.flatMap((found) => Effect.forEach(found, ([, make]) => make)));
11877
+ const available = (entries) => Effect.filter([...new Set(entries.map(([command]) => command))], onPath, { concurrency: "unbounded" }).pipe(Effect.map((found) => entries.filter(([command]) => found.includes(command))));
11878
+ const systemProviders = available(system$1).pipe(Effect.flatMap((found) => Effect.forEach(found, ([, make]) => make, { concurrency: "unbounded" })));
11829
11879
  const project$1 = [
11830
11880
  ["go", {
11831
11881
  manifests: ["go.mod"],
@@ -11851,9 +11901,8 @@ const project$1 = [
11851
11901
  const manifests = project$1.flatMap(([, kind]) => kind.manifests);
11852
11902
  const projectProviders = (given) => Effect.gen(function* () {
11853
11903
  const dir = yield* (yield* FileSystem.FileSystem).realPath(given).pipe(Effect.orElseSucceed(() => given));
11854
- const found = yield* available(project$1);
11855
- const nested = yield* nestedDirs(dir, manifests);
11856
- return (yield* Effect.forEach(found, ([, kind]) => kind.discover(dir, [...new Set(kind.manifests.flatMap(nested))]))).flat();
11904
+ const [found, nested] = yield* Effect.all([available(project$1), nestedDirs(dir, manifests)], { concurrency: "unbounded" });
11905
+ return (yield* Effect.forEach(found, ([, kind]) => kind.discover(dir, [...new Set(kind.manifests.flatMap(nested))]), { concurrency: "unbounded" })).flat();
11857
11906
  });
11858
11907
  const layer$3 = Layer.effect(ProviderSource, Effect.gen(function* () {
11859
11908
  const context = yield* Effect.context();
@@ -11963,7 +12012,7 @@ const message = (version) => {
11963
12012
  };
11964
12013
  const lookup$1 = Effect.fn("npm.lookup")(function* (client, wanted) {
11965
12014
  const path = wanted.name.replace("/", "%2F");
11966
- const [packument, downloads] = yield* Effect.all([getJson(client, `https://registry.npmjs.org/${path}`, Packument), getJson(client, `https://api.npmjs.org/downloads/point/last-week/${wanted.name}`, Downloads).pipe(Effect.option)], { concurrency: 2 });
12015
+ const [packument, downloads] = yield* Effect.all([getJson(client, `https://registry.npmjs.org/${path}`, Packument), getJson(client, `https://api.npmjs.org/downloads/point/last-week/${wanted.name}`, Downloads).pipe(Effect.option)], { concurrency: "unbounded" });
11967
12016
  const versions = packument.versions ?? {};
11968
12017
  const latest = packument["dist-tags"]?.latest;
11969
12018
  const repository = Predicate.isString(packument.repository) ? packument.repository : packument.repository?.url;
@@ -12003,7 +12052,7 @@ const repositoryKeys = [
12003
12052
  "GitHub"
12004
12053
  ];
12005
12054
  const lookup = Effect.fn("pypi.lookup")(function* (client, wanted) {
12006
- const [project, recent] = yield* Effect.all([getJson(client, `https://pypi.org/pypi/${wanted.name}/json`, Project), getJson(client, `https://pypistats.org/api/packages/${wanted.name.toLowerCase()}/recent`, Recent).pipe(Effect.option)], { concurrency: 2 });
12055
+ const [project, recent] = yield* Effect.all([getJson(client, `https://pypi.org/pypi/${wanted.name}/json`, Project), getJson(client, `https://pypistats.org/api/packages/${wanted.name.toLowerCase()}/recent`, Recent).pipe(Effect.option)], { concurrency: "unbounded" });
12007
12056
  const urls = project.info.project_urls ?? {};
12008
12057
  const repository = repositoryKeys.map((key) => urls[key]).find((url) => url !== void 0);
12009
12058
  const homepage = urls["Homepage"] ?? project.info.home_page ?? void 0;
@@ -12597,12 +12646,10 @@ const layer$1 = (cacheDir) => Layer.succeed(UpdateLog, UpdateLog.of({
12597
12646
  const directory = path.join(cacheDir, "updates");
12598
12647
  const names = (await readdir(directory).catch(() => [])).filter((name) => name.endsWith(".jsonl")).toSorted();
12599
12648
  const found = [];
12600
- for (const name of names) {
12601
- const text = await readFile(path.join(directory, name), "utf-8").catch(() => "");
12602
- for (const line of text.split("\n")) {
12603
- const entry = Option.getOrUndefined(decodeLine(line));
12604
- if (entry?.scope === scope && Date.parse(entry.at) >= since) found.push(entry);
12605
- }
12649
+ const texts = await Promise.all(names.map(async (name) => await readFile(path.join(directory, name), "utf-8").catch(() => "")));
12650
+ for (const text of texts) for (const line of text.split("\n")) {
12651
+ const entry = Option.getOrUndefined(decodeLine(line));
12652
+ if (entry?.scope === scope && Date.parse(entry.at) >= since) found.push(entry);
12606
12653
  }
12607
12654
  return found;
12608
12655
  })
@@ -13346,8 +13393,8 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
13346
13393
  };
13347
13394
  });
13348
13395
  const recallAll = Effect.gen(function* () {
13349
- const found = yield* earlier(yield* SubscriptionRef.get(state));
13350
- const logged = yield* fromLog(yield* SubscriptionRef.get(state));
13396
+ const before = yield* SubscriptionRef.get(state);
13397
+ const [found, logged] = yield* Effect.all([earlier(before), fromLog(before)], { concurrency: "unbounded" });
13351
13398
  yield* update((latest) => ({
13352
13399
  ...latest,
13353
13400
  installed: {
@@ -13366,15 +13413,14 @@ const layer = Layer.effect(Session, Effect.gen(function* () {
13366
13413
  const identity = identityOf(pkg, current.mode);
13367
13414
  if (identity !== void 0 && current.audits[jobKey(identity)]?._tag !== "Running") wanted.set(jobKey(identity), identity);
13368
13415
  }
13369
- yield* Effect.forEach(wanted.values(), audits.recall, {
13370
- concurrency: 4,
13371
- discard: true
13372
- });
13373
13416
  const offered = packagesOf(current).flatMap((pkg) => {
13374
13417
  const identity = pkg.target === void 0 ? void 0 : identityOf(pkg, current.mode);
13375
13418
  return identity === void 0 ? [] : [identity];
13376
13419
  });
13377
- const majors = yield* Effect.forEach(offered, (identity) => audits.majors(identity).pipe(Effect.map((identityMajors) => [jobKey(identity), identityMajors])), { concurrency: 4 });
13420
+ const [, majors] = yield* Effect.all([Effect.forEach(wanted.values(), audits.recall, {
13421
+ concurrency: 4,
13422
+ discard: true
13423
+ }), Effect.forEach(offered, (identity) => audits.majors(identity).pipe(Effect.map((identityMajors) => [jobKey(identity), identityMajors])), { concurrency: 4 })], { concurrency: "unbounded" });
13378
13424
  yield* update((latest) => ({
13379
13425
  ...latest,
13380
13426
  majors: {