@timurproko/a1 0.1.1-dev.1 → 0.1.1-dev.3

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.
@@ -2,6 +2,8 @@ import { createHash } from "node:crypto";
2
2
  import { lstat, readFile, readdir, realpath } from "node:fs/promises";
3
3
  import { basename, dirname, isAbsolute, relative, resolve, sep } from "node:path";
4
4
  import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
5
+ import { mapWithConcurrency } from "./concurrency.js";
6
+ const RELEASE_FILE_IO_CONCURRENCY = 32;
5
7
  export const PRODUCT_PACKAGE_NAME = PRODUCT_IDENTITY.packageName;
6
8
  /**
7
9
  * Derive release execution identity only from installed distribution metadata and
@@ -23,20 +25,20 @@ export async function deriveReleaseIdentity(packageRoot) {
23
25
  await collectFiles(canonicalRoot, absolute, paths);
24
26
  }
25
27
  await collectDependencyClosure(canonicalRoot, canonicalRoot, manifest, paths, new Set());
26
- const files = [];
27
- for (const path of [...paths].sort()) {
28
+ const sortedPaths = [...paths].sort();
29
+ const files = await mapWithConcurrency(sortedPaths, RELEASE_FILE_IO_CONCURRENCY, async (path) => {
28
30
  const absolute = resolveWithin(canonicalRoot, path);
29
31
  const metadata = await lstat(absolute);
30
32
  if (!metadata.isFile())
31
33
  throw new Error(`release payload is not a regular file: ${path}`);
32
34
  const bytes = await readFile(absolute);
33
- files.push({
35
+ return {
34
36
  path: normalizeRelative(path),
35
37
  bytes: bytes.length,
36
38
  sha256: createHash("sha256").update(bytes).digest("hex"),
37
39
  executable: (metadata.mode & 0o111) !== 0,
38
- });
39
- }
40
+ };
41
+ });
40
42
  const digest = createHash("sha256");
41
43
  for (const file of files)
42
44
  digest.update(`${file.path}\0${file.bytes}\0${file.sha256}\0${file.executable ? 1 : 0}\n`);
@@ -50,5 +50,5 @@ export interface UpdateTransactionJournal {
50
50
  clearCompleted(): Promise<void>;
51
51
  }
52
52
  export declare function createNpmProcessRunner(platform?: NodeJS.Platform): UpdateProcessRunner;
53
- export declare function createUpdateLifecycleCoordinator(environment?: NodeJS.ProcessEnv, fileSystem?: UpdateFileSystem): UpdateLifecycleCoordinator;
53
+ export declare function createUpdateLifecycleCoordinator(environment?: NodeJS.ProcessEnv, fileSystem?: UpdateFileSystem, output?: UpdateOutput): UpdateLifecycleCoordinator;
54
54
  export declare function runSelfUpdate(options: SelfUpdateOptions): Promise<number>;
@@ -40,7 +40,7 @@ export function createNpmProcessRunner(platform = process.platform) {
40
40
  } });
41
41
  });
42
42
  }
43
- export function createUpdateLifecycleCoordinator(environment = process.env, fileSystem = defaultFileSystem) {
43
+ export function createUpdateLifecycleCoordinator(environment = process.env, fileSystem = defaultFileSystem, output = defaultOutput) {
44
44
  const paths = resolveProductPaths(environment);
45
45
  const stateStore = new CohortStateStore(paths.dataDir);
46
46
  return {
@@ -106,7 +106,9 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
106
106
  }
107
107
  },
108
108
  async activateInstalled(packageRoot, targetVersion, phase) {
109
- const candidate = await materializeRelease(packageRoot, paths.dataDir);
109
+ const candidate = await materializeRelease(packageRoot, paths.dataDir, {
110
+ onProgress: progress => output.stdout(`${PRODUCT_TEXT.diagnostic(`installing ${progress.fileCount} files.`)}\n`),
111
+ });
110
112
  if (candidate.packageVersion !== targetVersion)
111
113
  throw new Error(`installed ${PRODUCT_TEXT.displayName} version ${candidate.packageVersion} does not match target ${targetVersion}`);
112
114
  await stateStore.recordCandidate(candidate);
@@ -170,7 +172,7 @@ export async function runSelfUpdate(options) {
170
172
  }
171
173
  const environment = options.environment ?? process.env;
172
174
  const paths = resolveProductPaths(environment);
173
- const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem);
175
+ const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem, output);
174
176
  const transactionStore = options.transactionStore ?? new UpdateTransactionStore(paths.dataDir);
175
177
  let transaction = await transactionStore.read();
176
178
  try {
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { appendFileSync, mkdirSync } from "node:fs";
3
- import { assertImmutableExecutionRoot, readMaterializedRelease } from "../release/index.js";
3
+ import { resolve } from "node:path";
4
+ import { assertImmutableExecutionRoot, readCertifiedReleaseManifest } from "../release/index.js";
4
5
  import { ControlStore } from "../storage/index.js";
5
6
  import { resolveProductPaths } from "./paths.js";
6
7
  import { SupervisorServer } from "./server.js";
@@ -10,11 +11,11 @@ export async function runSupervisor() {
10
11
  mkdirSync(paths.runtimeDir, { recursive: true, mode: 0o700 });
11
12
  const log = (message) => appendFileSync(paths.supervisorLogPath, `${new Date().toISOString()} ${message}\n`);
12
13
  const releaseRoot = process.env[PRODUCT_IDENTITY.environment.releaseRoot];
13
- if (!releaseRoot)
14
+ const releaseId = process.env[PRODUCT_IDENTITY.environment.releaseId];
15
+ const contentDigest = process.env[PRODUCT_IDENTITY.environment.releaseDigest];
16
+ if (!releaseRoot || !releaseId || !contentDigest)
14
17
  throw new Error(PRODUCT_TEXT.diagnostic("supervisor must be launched from a verified immutable release"));
15
- const release = await readMaterializedRelease(releaseRoot);
16
- if (process.env[PRODUCT_IDENTITY.environment.releaseId] !== release.releaseId)
17
- throw new Error(PRODUCT_TEXT.diagnostic("selected release identity does not match its verified manifest"));
18
+ const release = await readCertifiedReleaseManifest({ releaseRoot, releaseId, contentDigest }, resolve(paths.dataDir, "releases"));
18
19
  await assertImmutableExecutionRoot(release, paths.dataDir);
19
20
  const bootNonce = randomUUID();
20
21
  const store = new ControlStore(paths.databasePath, bootNonce);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timurproko/a1",
3
- "version": "0.1.1-dev.1",
3
+ "version": "0.1.1-dev.3",
4
4
  "description": "Standalone terminal workspace for supervised native and managed agents",
5
5
  "type": "module",
6
6
  "packageManager": "npm@11.13.0",
@@ -24,6 +24,7 @@
24
24
  "check:architecture": "node scripts/check-architecture.mjs && node scripts/product-identifier-policy.mjs --check && node scripts/check-product-identity-boundaries.mjs && node scripts/check-package-identity.mjs && node scripts/check-pinned-pi-source-ledger.mjs && node scripts/check-terminal-host-provenance.mjs",
25
25
  "check:customization-ready": "node scripts/check-owned-ui-customization-prerequisites.mjs",
26
26
  "check:deprecated": "node scripts/check-deprecated-dependencies.mjs",
27
+ "branches:prune": "node scripts/prune-merged-branches.mjs",
27
28
  "check": "npm run typecheck && npm run check:architecture && npm run check:customization-ready && npm run check:deprecated && npm test && npm run test:release",
28
29
  "validate:agent": "npm run check",
29
30
  "publish:next": "tsx scripts/publish-next.ts",