@odla-ai/harness 0.11.11 → 0.11.13

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/node.d.cts CHANGED
@@ -596,6 +596,15 @@ interface CodeToolBrokerOptions {
596
596
  onDecision?(decision: CodeToolDecision): Promise<void> | void;
597
597
  }
598
598
 
599
+ /** A host directory (or, for build products, a file) lent into a run's workspace. */
600
+ interface LentDirectory {
601
+ /** Absolute path on the host. */
602
+ source: string;
603
+ /** Workspace-relative path it appears at. A mounted tree's last segment must be a reserved name. */
604
+ mountAs: string;
605
+ /** The workspace package it belongs to. A workspace without that directory does not receive the entry. */
606
+ within?: string;
607
+ }
599
608
  /**
600
609
  * An installed dependency tree lent to a recipe for the length of one run.
601
610
  *
@@ -608,7 +617,27 @@ interface RecipeDependencies {
608
617
  /** Where it appears inside the workspace. Must be a reserved name, so the
609
618
  * agent still cannot address it. */
610
619
  mountAs?: string;
611
- }
620
+ /** Workspace packages whose own `node_modules` the install produced (a
621
+ * version the root tree could not hoist), each lent at its own path. */
622
+ nested?: LentDirectory[];
623
+ /** The host's build output per workspace package, copied into the run's
624
+ * workspace wherever it has none, so a test can import a sibling package
625
+ * the way npm resolves it: through its `dist`. */
626
+ products?: LentDirectory[];
627
+ /** When set, every run gets its own copy-on-write clone of the tree under
628
+ * this directory and mounts it writable. vite and vitest write caches and
629
+ * bundled configs into `node_modules` and refuse a read-only one. */
630
+ runsDir?: string;
631
+ /** True only on the per-run clone `lendDependencies` makes. The shared tree
632
+ * is never mounted writable. */
633
+ writable?: boolean;
634
+ }
635
+ /** Refuse a lent path that leaves the workspace. */
636
+ declare function assertLentPath(mountAs: string): void;
637
+ /** Refuse any mounted tree the agent could address: inside the workspace, and ending in a reserved name. */
638
+ declare function assertReservedMount(mountAs: string): void;
639
+ /** Every directory a dependency set lends: the root tree first, then each nested one. */
640
+ declare function lentDirectories(dependencies: RecipeDependencies): LentDirectory[];
612
641
  /**
613
642
  * Wrap an executor so `dependencies.source` is present during each recipe run.
614
643
  *
@@ -710,8 +739,9 @@ interface TheseusRuntimeEngineOptions {
710
739
  /** Injectable agent attempt. Defaults to runAgent over the brokered surface. */
711
740
  runAgentAttempt?: (options: CodeAgentAttemptOptions) => Promise<CodeAgentAttemptResult>;
712
741
  recipeExecutor?: CodeRecipeExecutor;
713
- /** The host's installed dependency tree, lent read-only to every recipe
714
- * container so a real test runner can be a proof in an offline sandbox. */
742
+ /** The host's prepared dependency tree, lent to every recipe container (as
743
+ * the run's own writable clone when the set allows one) so a real test
744
+ * runner can be a proof in an offline sandbox. */
715
745
  recipeDependencies?: RecipeDependencies | null;
716
746
  /** Owner-visible and terminal-visible bounded runtime failures. */
717
747
  onDiagnostic?: (message: string) => void;
@@ -1616,10 +1646,10 @@ declare const DEPENDENCY_INSTALL_TIMEOUT_MS: number;
1616
1646
  /** What preparing a tree needs: the engine and pinned image, the repository, and the cache root; `run` is injectable for tests. */
1617
1647
  interface DependencyCacheInput {
1618
1648
  engine: ContainerEngine;
1619
- /** The pinned recipe image; its node and npm install the tree. */
1649
+ /** The pinned recipe image; its node installs the tree. */
1620
1650
  image: string;
1621
1651
  repoRoot: string;
1622
- /** Where trees live: `<cacheRoot>/<key>/node_modules`. */
1652
+ /** Where trees live: `<cacheRoot>/<key>/tree/node_modules`, with per-run clones under `<cacheRoot>/<key>/runs`. */
1623
1653
  cacheRoot: string;
1624
1654
  run?: (engine: ContainerEngine, args: string[], name: string, limits: {
1625
1655
  timeoutMs: number;
@@ -1627,15 +1657,24 @@ interface DependencyCacheInput {
1627
1657
  }) => Promise<CodeRecipeResult>;
1628
1658
  log?: (line: string) => void;
1629
1659
  }
1630
- /** The cache key: the lockfile's bytes, the image, and the architecture the container runs. Null without a lockfile. */
1631
- declare function dependencyCacheKey(repoRoot: string, image: string, arch?: NodeJS.Architecture): Promise<string | null>;
1660
+ /** The npm the repository generates its lockfile with: an exact `engines.npm`, or null when it pins none. */
1661
+ declare function pinnedNpmVersion(repoRoot: string): Promise<string | null>;
1662
+ /** The cache key: the lockfile's bytes, the image, the architecture the container runs, and the npm that installs. Null without a lockfile. */
1663
+ declare function dependencyCacheKey(repoRoot: string, image: string, arch?: NodeJS.Architecture, npmVersion?: string | null): Promise<string | null>;
1664
+ /** Every workspace directory the root manifest declares that has a package.json, repository-relative, in declaration order. */
1665
+ declare function workspaceDirs(repoRoot: string): Promise<string[]>;
1632
1666
  /** Copy only what npm ci needs: the root manifests and every workspace's package.json. Returns what was staged. */
1633
1667
  declare function stageManifests(repoRoot: string, stageDir: string): Promise<string[]>;
1634
- /** The helper's command: networked, writable stage, scripts disabled, nothing else of the host mounted. */
1635
- declare function dependencyInstallArgs(engine: ContainerEngine, image: string, stageDir: string, name: string): string[];
1668
+ /** The helper's command: networked, writable stage, scripts disabled, nothing else of the host mounted; the repository's npm when it pins one. */
1669
+ declare function dependencyInstallArgs(engine: ContainerEngine, image: string, stageDir: string, name: string, npmVersion?: string | null): string[];
1670
+ /** The lines of an npm failure worth reading: from `npm error code` on, never the usage boilerplate npm ends with. */
1671
+ declare function npmFailureSummary(stderr: string): string;
1636
1672
  /** The tree for this repository's lockfile, from the cache or freshly installed; null when there is no lockfile or the install failed. */
1637
1673
  declare function prepareContainerDependencies(input: DependencyCacheInput): Promise<RecipeDependencies | null>;
1638
1674
 
1675
+ /** The host checkout's build output to lend into a run's workspace: each package's `dist`, then every ignored file the policy allows. */
1676
+ declare function hostBuildProducts(repoRoot: string): Promise<LentDirectory[]>;
1677
+
1639
1678
  /** Every ordinary, policy-legal source path under `root`, sorted. */
1640
1679
  declare function registeredFiles(root: string, limit?: number): Promise<string[]>;
1641
1680
 
@@ -1647,10 +1686,27 @@ declare function createContainerRecipeExecutor(engine: ContainerEngine, options?
1647
1686
  }): CodeRecipeExecutor;
1648
1687
  /** Validate immutable recipe identity, digest image, command, and resource bounds. */
1649
1688
  declare function assertCodeBuildRecipe(recipe: CodeBuildRecipe): void;
1689
+ /** The command's own output: the Apple engine prefixes stderr with its image and kernel progress
1690
+ * (`[1/6] Fetching image …`), which is the engine's, not the recipe's, and it was all a bounded
1691
+ * failure reason ever showed of a red test run (bug eff741ee). */
1692
+ declare function recipeOutput(engine: ContainerEngine, stderr: string): string;
1650
1693
  /** Run one container command to completion under an output cap and a timeout, never through a shell. */
1651
1694
  declare function runContainerCommand(engine: ContainerEngine, args: string[], name: string, recipe: {
1652
1695
  timeoutMs: number;
1653
1696
  maxOutputBytes: number;
1654
1697
  }, signal?: AbortSignal): Promise<CodeRecipeResult>;
1655
1698
 
1656
- export { CODE_PATCH_PATH, CODE_RUNTIME_PROTOCOL_VERSION, type CodeAgentAttemptOptions, type CodeAgentAttemptResult, type CodeAgentRun, type CodeBuildRecipe, type CodeExpectedArtifact, type CodeLocalSourceDescriptor, type CodeMemory, type CodeMemoryEvidence, type CodeMemoryKind, type CodeMemoryStore, type CodeRecipeExecutor, type CodeRecipeResult, type CodeRuntimeAgentControlPlane, type CodeRuntimeBinding, type CodeRuntimeCandidateResponse, type CodeRuntimeCapabilities, CodeRuntimeCheckpointManager, type CodeRuntimeClientOptions, type CodeRuntimeCollaborationSkillManifest, type CodeRuntimeCollaborationToolManifest, type CodeRuntimeCollaborationToolRequest, type CodeRuntimeCommand, type CodeRuntimeCommandEngine, type CodeRuntimeCommandKind, type CodeRuntimeCommandResult, CodeRuntimeControlError, type CodeRuntimeControlPlane, type CodeRuntimeInferenceOptions, type CodeRuntimeLoopOptions, type CodeRuntimeMemory, type CodeRuntimeNewMemory, CodeRuntimeReconciler, type CodeRuntimeReviewRequest, type CodeRuntimeReviewResponse, type CodeRuntimeSnapshot, type CodeRuntimeSourceArchive, type CodeRuntimeSourceSnapshot, type CodeSkillOpts, type CodeSurface, type CodeToolBrokerOptions, type CodeToolCallRecord, type CodeToolDecision, type CodeVerificationEvidence, type CodeVerificationLog, type CodeVerificationPolicy, type ContainerEngine, type ContainerEngineSelectionOptions, type ContainerEngineVerificationOptions, type ContainerLimits, type ContainerRunOptions, type ContainerRunResult, type CreateCodeWorkspaceCheckpointInput, DEPENDENCY_INSTALL_TIMEOUT_MS, type DecomposedRun, DecompositionError, type DependencyCacheInput, type GoalAttempt, type GoalAttemptInput, type GoalAttemptOutcome, type GoalAttemptRecord, type GoalBudget, type GoalEvent, type GoalOutcome, type GoalRun, type GoalRunSpec, type GoalStoppedReason, type GoalStrategy, type HarnessRunnerOptions, type IntegrateOptions, type IntegrationStep, MAX_MEMORY_BODY, MEASURED_PREMIUM, type MaterializedCodeSource, type MaterializedGitTree, type NewCodeMemory, PROOF_RECIPE_PREFIX, type PrepareRuntimeCheckpointInput, type PreparedRuntimeCheckpoint, REPOSITORY_RECIPES_FILE, type RacedAttemptOptions, type RacedOutcome, type RecallOptions, type RecipeDependencies, type RepositoryRecipeEnvelope, type ResolvedCodeRecipes, type RestoreCodeWorkspaceCheckpointInput, type RestoredCodeWorkspaceCheckpoint, type RunCodeAgentOptions, type RuntimeCheckpointSession, SYSTEM_PROMPT_FOR, type StageWorkspaceOptions, type StagedWorkspace, type StrategyChoice, type StrategySignals, type SubGoal, type SubGoalResult, TheseusRuntimeEngine, type TheseusRuntimeEngineOptions, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, type VerifyCodeCandidateInput, applyCodePatch, applyPatchDialectToDiff, assertCodeBuildRecipe, assertDisjointPlan, assertPinnedImage, attachCodeRuntimeReferences, buildContainerRunArgs, buildRecipeContainerArgs, chooseStrategy, codeSkill, createCodeRuntimeControlClient, createCodeRuntimeInference, createCodeRuntimeSessionSkillLoader, createCodeToolBroker, createCodeWorkspaceCheckpoint, createContainerRecipeExecutor, dependencyCacheKey, dependencyInstallArgs, describeCodeRecipes, describeGateFailure, describePatchFailure, digestStagedWorkspace, feedbackIsActionable, hasContextFreeHunk, hazardFromAttempt, installedDependencies, integrateSubGoals, isCheckpointEffectCompleted, materializeCodeRuntimeArchive, materializeCodeRuntimeSource, materializeCommandWorkspace, materializeGitTree, outcomeCloses, outcomeMemory, parseRepositoryRecipes, patchPaths, planReachCollisions, prepareContainerDependencies, prepareRuntimeCheckpoint, racedAttempt, readOnlyNotice, readRepositoryRecipes, recallAbout, registeredFiles, renderMemories, renderOutcome, resolveCodePath, resolveCodeRecipes, restoreCodeWorkspaceCheckpoint, runCodeAgent, runCodeAgentAttempt, runCodeRuntimeHeartbeatLoop, runContainerAttempt, runContainerCommand, runGoal, runHarnessRunner, runLeasedAttempt, runtimeMemoryStore, safeWorkspaceLabel, selectContainerEngine, selectWinner, sessionRecipesFor, sessionSkillsFor, stageManifests, stageWorkspace, stageWorkspacePair, straySubGoalFiles, stripPatchEnvelope, validateCodePatch, validateMemory, validateRelativePath, verifyCodeCandidate, verifyContainerEngineBoundary, withProofRecipes, withRecipeDependencies };
1699
+ /** A dependency set lent to one run, and how to give it back. */
1700
+ interface LentDependencies {
1701
+ dependencies: RecipeDependencies | null;
1702
+ /** Remove the run's clone. A no-op when nothing was cloned. */
1703
+ release(): Promise<void>;
1704
+ }
1705
+ /** Clone a directory tree, sharing blocks with the original where the filesystem can and copying otherwise. */
1706
+ declare function cloneTree(source: string, target: string, platform?: NodeJS.Platform): Promise<void>;
1707
+ /** Give one run its own writable clone of the tree when the set allows it; otherwise lend the set as it is, read-only. */
1708
+ declare function lendDependencies(dependencies: RecipeDependencies | null, runId: string): Promise<LentDependencies>;
1709
+ /** Copy the host's build output into the workspace wherever its package exists there and it has no copy of its own. Returns what was lent. */
1710
+ declare function lendBuildProducts(products: readonly LentDirectory[], workspaceDir: string): Promise<string[]>;
1711
+
1712
+ export { CODE_PATCH_PATH, CODE_RUNTIME_PROTOCOL_VERSION, type CodeAgentAttemptOptions, type CodeAgentAttemptResult, type CodeAgentRun, type CodeBuildRecipe, type CodeExpectedArtifact, type CodeLocalSourceDescriptor, type CodeMemory, type CodeMemoryEvidence, type CodeMemoryKind, type CodeMemoryStore, type CodeRecipeExecutor, type CodeRecipeResult, type CodeRuntimeAgentControlPlane, type CodeRuntimeBinding, type CodeRuntimeCandidateResponse, type CodeRuntimeCapabilities, CodeRuntimeCheckpointManager, type CodeRuntimeClientOptions, type CodeRuntimeCollaborationSkillManifest, type CodeRuntimeCollaborationToolManifest, type CodeRuntimeCollaborationToolRequest, type CodeRuntimeCommand, type CodeRuntimeCommandEngine, type CodeRuntimeCommandKind, type CodeRuntimeCommandResult, CodeRuntimeControlError, type CodeRuntimeControlPlane, type CodeRuntimeInferenceOptions, type CodeRuntimeLoopOptions, type CodeRuntimeMemory, type CodeRuntimeNewMemory, CodeRuntimeReconciler, type CodeRuntimeReviewRequest, type CodeRuntimeReviewResponse, type CodeRuntimeSnapshot, type CodeRuntimeSourceArchive, type CodeRuntimeSourceSnapshot, type CodeSkillOpts, type CodeSurface, type CodeToolBrokerOptions, type CodeToolCallRecord, type CodeToolDecision, type CodeVerificationEvidence, type CodeVerificationLog, type CodeVerificationPolicy, type ContainerEngine, type ContainerEngineSelectionOptions, type ContainerEngineVerificationOptions, type ContainerLimits, type ContainerRunOptions, type ContainerRunResult, type CreateCodeWorkspaceCheckpointInput, DEPENDENCY_INSTALL_TIMEOUT_MS, type DecomposedRun, DecompositionError, type DependencyCacheInput, type GoalAttempt, type GoalAttemptInput, type GoalAttemptOutcome, type GoalAttemptRecord, type GoalBudget, type GoalEvent, type GoalOutcome, type GoalRun, type GoalRunSpec, type GoalStoppedReason, type GoalStrategy, type HarnessRunnerOptions, type IntegrateOptions, type IntegrationStep, type LentDependencies, type LentDirectory, MAX_MEMORY_BODY, MEASURED_PREMIUM, type MaterializedCodeSource, type MaterializedGitTree, type NewCodeMemory, PROOF_RECIPE_PREFIX, type PrepareRuntimeCheckpointInput, type PreparedRuntimeCheckpoint, REPOSITORY_RECIPES_FILE, type RacedAttemptOptions, type RacedOutcome, type RecallOptions, type RecipeDependencies, type RepositoryRecipeEnvelope, type ResolvedCodeRecipes, type RestoreCodeWorkspaceCheckpointInput, type RestoredCodeWorkspaceCheckpoint, type RunCodeAgentOptions, type RuntimeCheckpointSession, SYSTEM_PROMPT_FOR, type StageWorkspaceOptions, type StagedWorkspace, type StrategyChoice, type StrategySignals, type SubGoal, type SubGoalResult, TheseusRuntimeEngine, type TheseusRuntimeEngineOptions, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, type VerifyCodeCandidateInput, applyCodePatch, applyPatchDialectToDiff, assertCodeBuildRecipe, assertDisjointPlan, assertLentPath, assertPinnedImage, assertReservedMount, attachCodeRuntimeReferences, buildContainerRunArgs, buildRecipeContainerArgs, chooseStrategy, cloneTree, codeSkill, createCodeRuntimeControlClient, createCodeRuntimeInference, createCodeRuntimeSessionSkillLoader, createCodeToolBroker, createCodeWorkspaceCheckpoint, createContainerRecipeExecutor, dependencyCacheKey, dependencyInstallArgs, describeCodeRecipes, describeGateFailure, describePatchFailure, digestStagedWorkspace, feedbackIsActionable, hasContextFreeHunk, hazardFromAttempt, hostBuildProducts, installedDependencies, integrateSubGoals, isCheckpointEffectCompleted, lendBuildProducts, lendDependencies, lentDirectories, materializeCodeRuntimeArchive, materializeCodeRuntimeSource, materializeCommandWorkspace, materializeGitTree, npmFailureSummary, outcomeCloses, outcomeMemory, parseRepositoryRecipes, patchPaths, pinnedNpmVersion, planReachCollisions, prepareContainerDependencies, prepareRuntimeCheckpoint, racedAttempt, readOnlyNotice, readRepositoryRecipes, recallAbout, recipeOutput, registeredFiles, renderMemories, renderOutcome, resolveCodePath, resolveCodeRecipes, restoreCodeWorkspaceCheckpoint, runCodeAgent, runCodeAgentAttempt, runCodeRuntimeHeartbeatLoop, runContainerAttempt, runContainerCommand, runGoal, runHarnessRunner, runLeasedAttempt, runtimeMemoryStore, safeWorkspaceLabel, selectContainerEngine, selectWinner, sessionRecipesFor, sessionSkillsFor, stageManifests, stageWorkspace, stageWorkspacePair, straySubGoalFiles, stripPatchEnvelope, validateCodePatch, validateMemory, validateRelativePath, verifyCodeCandidate, verifyContainerEngineBoundary, withProofRecipes, withRecipeDependencies, workspaceDirs };
package/dist/node.d.ts CHANGED
@@ -596,6 +596,15 @@ interface CodeToolBrokerOptions {
596
596
  onDecision?(decision: CodeToolDecision): Promise<void> | void;
597
597
  }
598
598
 
599
+ /** A host directory (or, for build products, a file) lent into a run's workspace. */
600
+ interface LentDirectory {
601
+ /** Absolute path on the host. */
602
+ source: string;
603
+ /** Workspace-relative path it appears at. A mounted tree's last segment must be a reserved name. */
604
+ mountAs: string;
605
+ /** The workspace package it belongs to. A workspace without that directory does not receive the entry. */
606
+ within?: string;
607
+ }
599
608
  /**
600
609
  * An installed dependency tree lent to a recipe for the length of one run.
601
610
  *
@@ -608,7 +617,27 @@ interface RecipeDependencies {
608
617
  /** Where it appears inside the workspace. Must be a reserved name, so the
609
618
  * agent still cannot address it. */
610
619
  mountAs?: string;
611
- }
620
+ /** Workspace packages whose own `node_modules` the install produced (a
621
+ * version the root tree could not hoist), each lent at its own path. */
622
+ nested?: LentDirectory[];
623
+ /** The host's build output per workspace package, copied into the run's
624
+ * workspace wherever it has none, so a test can import a sibling package
625
+ * the way npm resolves it: through its `dist`. */
626
+ products?: LentDirectory[];
627
+ /** When set, every run gets its own copy-on-write clone of the tree under
628
+ * this directory and mounts it writable. vite and vitest write caches and
629
+ * bundled configs into `node_modules` and refuse a read-only one. */
630
+ runsDir?: string;
631
+ /** True only on the per-run clone `lendDependencies` makes. The shared tree
632
+ * is never mounted writable. */
633
+ writable?: boolean;
634
+ }
635
+ /** Refuse a lent path that leaves the workspace. */
636
+ declare function assertLentPath(mountAs: string): void;
637
+ /** Refuse any mounted tree the agent could address: inside the workspace, and ending in a reserved name. */
638
+ declare function assertReservedMount(mountAs: string): void;
639
+ /** Every directory a dependency set lends: the root tree first, then each nested one. */
640
+ declare function lentDirectories(dependencies: RecipeDependencies): LentDirectory[];
612
641
  /**
613
642
  * Wrap an executor so `dependencies.source` is present during each recipe run.
614
643
  *
@@ -710,8 +739,9 @@ interface TheseusRuntimeEngineOptions {
710
739
  /** Injectable agent attempt. Defaults to runAgent over the brokered surface. */
711
740
  runAgentAttempt?: (options: CodeAgentAttemptOptions) => Promise<CodeAgentAttemptResult>;
712
741
  recipeExecutor?: CodeRecipeExecutor;
713
- /** The host's installed dependency tree, lent read-only to every recipe
714
- * container so a real test runner can be a proof in an offline sandbox. */
742
+ /** The host's prepared dependency tree, lent to every recipe container (as
743
+ * the run's own writable clone when the set allows one) so a real test
744
+ * runner can be a proof in an offline sandbox. */
715
745
  recipeDependencies?: RecipeDependencies | null;
716
746
  /** Owner-visible and terminal-visible bounded runtime failures. */
717
747
  onDiagnostic?: (message: string) => void;
@@ -1616,10 +1646,10 @@ declare const DEPENDENCY_INSTALL_TIMEOUT_MS: number;
1616
1646
  /** What preparing a tree needs: the engine and pinned image, the repository, and the cache root; `run` is injectable for tests. */
1617
1647
  interface DependencyCacheInput {
1618
1648
  engine: ContainerEngine;
1619
- /** The pinned recipe image; its node and npm install the tree. */
1649
+ /** The pinned recipe image; its node installs the tree. */
1620
1650
  image: string;
1621
1651
  repoRoot: string;
1622
- /** Where trees live: `<cacheRoot>/<key>/node_modules`. */
1652
+ /** Where trees live: `<cacheRoot>/<key>/tree/node_modules`, with per-run clones under `<cacheRoot>/<key>/runs`. */
1623
1653
  cacheRoot: string;
1624
1654
  run?: (engine: ContainerEngine, args: string[], name: string, limits: {
1625
1655
  timeoutMs: number;
@@ -1627,15 +1657,24 @@ interface DependencyCacheInput {
1627
1657
  }) => Promise<CodeRecipeResult>;
1628
1658
  log?: (line: string) => void;
1629
1659
  }
1630
- /** The cache key: the lockfile's bytes, the image, and the architecture the container runs. Null without a lockfile. */
1631
- declare function dependencyCacheKey(repoRoot: string, image: string, arch?: NodeJS.Architecture): Promise<string | null>;
1660
+ /** The npm the repository generates its lockfile with: an exact `engines.npm`, or null when it pins none. */
1661
+ declare function pinnedNpmVersion(repoRoot: string): Promise<string | null>;
1662
+ /** The cache key: the lockfile's bytes, the image, the architecture the container runs, and the npm that installs. Null without a lockfile. */
1663
+ declare function dependencyCacheKey(repoRoot: string, image: string, arch?: NodeJS.Architecture, npmVersion?: string | null): Promise<string | null>;
1664
+ /** Every workspace directory the root manifest declares that has a package.json, repository-relative, in declaration order. */
1665
+ declare function workspaceDirs(repoRoot: string): Promise<string[]>;
1632
1666
  /** Copy only what npm ci needs: the root manifests and every workspace's package.json. Returns what was staged. */
1633
1667
  declare function stageManifests(repoRoot: string, stageDir: string): Promise<string[]>;
1634
- /** The helper's command: networked, writable stage, scripts disabled, nothing else of the host mounted. */
1635
- declare function dependencyInstallArgs(engine: ContainerEngine, image: string, stageDir: string, name: string): string[];
1668
+ /** The helper's command: networked, writable stage, scripts disabled, nothing else of the host mounted; the repository's npm when it pins one. */
1669
+ declare function dependencyInstallArgs(engine: ContainerEngine, image: string, stageDir: string, name: string, npmVersion?: string | null): string[];
1670
+ /** The lines of an npm failure worth reading: from `npm error code` on, never the usage boilerplate npm ends with. */
1671
+ declare function npmFailureSummary(stderr: string): string;
1636
1672
  /** The tree for this repository's lockfile, from the cache or freshly installed; null when there is no lockfile or the install failed. */
1637
1673
  declare function prepareContainerDependencies(input: DependencyCacheInput): Promise<RecipeDependencies | null>;
1638
1674
 
1675
+ /** The host checkout's build output to lend into a run's workspace: each package's `dist`, then every ignored file the policy allows. */
1676
+ declare function hostBuildProducts(repoRoot: string): Promise<LentDirectory[]>;
1677
+
1639
1678
  /** Every ordinary, policy-legal source path under `root`, sorted. */
1640
1679
  declare function registeredFiles(root: string, limit?: number): Promise<string[]>;
1641
1680
 
@@ -1647,10 +1686,27 @@ declare function createContainerRecipeExecutor(engine: ContainerEngine, options?
1647
1686
  }): CodeRecipeExecutor;
1648
1687
  /** Validate immutable recipe identity, digest image, command, and resource bounds. */
1649
1688
  declare function assertCodeBuildRecipe(recipe: CodeBuildRecipe): void;
1689
+ /** The command's own output: the Apple engine prefixes stderr with its image and kernel progress
1690
+ * (`[1/6] Fetching image …`), which is the engine's, not the recipe's, and it was all a bounded
1691
+ * failure reason ever showed of a red test run (bug eff741ee). */
1692
+ declare function recipeOutput(engine: ContainerEngine, stderr: string): string;
1650
1693
  /** Run one container command to completion under an output cap and a timeout, never through a shell. */
1651
1694
  declare function runContainerCommand(engine: ContainerEngine, args: string[], name: string, recipe: {
1652
1695
  timeoutMs: number;
1653
1696
  maxOutputBytes: number;
1654
1697
  }, signal?: AbortSignal): Promise<CodeRecipeResult>;
1655
1698
 
1656
- export { CODE_PATCH_PATH, CODE_RUNTIME_PROTOCOL_VERSION, type CodeAgentAttemptOptions, type CodeAgentAttemptResult, type CodeAgentRun, type CodeBuildRecipe, type CodeExpectedArtifact, type CodeLocalSourceDescriptor, type CodeMemory, type CodeMemoryEvidence, type CodeMemoryKind, type CodeMemoryStore, type CodeRecipeExecutor, type CodeRecipeResult, type CodeRuntimeAgentControlPlane, type CodeRuntimeBinding, type CodeRuntimeCandidateResponse, type CodeRuntimeCapabilities, CodeRuntimeCheckpointManager, type CodeRuntimeClientOptions, type CodeRuntimeCollaborationSkillManifest, type CodeRuntimeCollaborationToolManifest, type CodeRuntimeCollaborationToolRequest, type CodeRuntimeCommand, type CodeRuntimeCommandEngine, type CodeRuntimeCommandKind, type CodeRuntimeCommandResult, CodeRuntimeControlError, type CodeRuntimeControlPlane, type CodeRuntimeInferenceOptions, type CodeRuntimeLoopOptions, type CodeRuntimeMemory, type CodeRuntimeNewMemory, CodeRuntimeReconciler, type CodeRuntimeReviewRequest, type CodeRuntimeReviewResponse, type CodeRuntimeSnapshot, type CodeRuntimeSourceArchive, type CodeRuntimeSourceSnapshot, type CodeSkillOpts, type CodeSurface, type CodeToolBrokerOptions, type CodeToolCallRecord, type CodeToolDecision, type CodeVerificationEvidence, type CodeVerificationLog, type CodeVerificationPolicy, type ContainerEngine, type ContainerEngineSelectionOptions, type ContainerEngineVerificationOptions, type ContainerLimits, type ContainerRunOptions, type ContainerRunResult, type CreateCodeWorkspaceCheckpointInput, DEPENDENCY_INSTALL_TIMEOUT_MS, type DecomposedRun, DecompositionError, type DependencyCacheInput, type GoalAttempt, type GoalAttemptInput, type GoalAttemptOutcome, type GoalAttemptRecord, type GoalBudget, type GoalEvent, type GoalOutcome, type GoalRun, type GoalRunSpec, type GoalStoppedReason, type GoalStrategy, type HarnessRunnerOptions, type IntegrateOptions, type IntegrationStep, MAX_MEMORY_BODY, MEASURED_PREMIUM, type MaterializedCodeSource, type MaterializedGitTree, type NewCodeMemory, PROOF_RECIPE_PREFIX, type PrepareRuntimeCheckpointInput, type PreparedRuntimeCheckpoint, REPOSITORY_RECIPES_FILE, type RacedAttemptOptions, type RacedOutcome, type RecallOptions, type RecipeDependencies, type RepositoryRecipeEnvelope, type ResolvedCodeRecipes, type RestoreCodeWorkspaceCheckpointInput, type RestoredCodeWorkspaceCheckpoint, type RunCodeAgentOptions, type RuntimeCheckpointSession, SYSTEM_PROMPT_FOR, type StageWorkspaceOptions, type StagedWorkspace, type StrategyChoice, type StrategySignals, type SubGoal, type SubGoalResult, TheseusRuntimeEngine, type TheseusRuntimeEngineOptions, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, type VerifyCodeCandidateInput, applyCodePatch, applyPatchDialectToDiff, assertCodeBuildRecipe, assertDisjointPlan, assertPinnedImage, attachCodeRuntimeReferences, buildContainerRunArgs, buildRecipeContainerArgs, chooseStrategy, codeSkill, createCodeRuntimeControlClient, createCodeRuntimeInference, createCodeRuntimeSessionSkillLoader, createCodeToolBroker, createCodeWorkspaceCheckpoint, createContainerRecipeExecutor, dependencyCacheKey, dependencyInstallArgs, describeCodeRecipes, describeGateFailure, describePatchFailure, digestStagedWorkspace, feedbackIsActionable, hasContextFreeHunk, hazardFromAttempt, installedDependencies, integrateSubGoals, isCheckpointEffectCompleted, materializeCodeRuntimeArchive, materializeCodeRuntimeSource, materializeCommandWorkspace, materializeGitTree, outcomeCloses, outcomeMemory, parseRepositoryRecipes, patchPaths, planReachCollisions, prepareContainerDependencies, prepareRuntimeCheckpoint, racedAttempt, readOnlyNotice, readRepositoryRecipes, recallAbout, registeredFiles, renderMemories, renderOutcome, resolveCodePath, resolveCodeRecipes, restoreCodeWorkspaceCheckpoint, runCodeAgent, runCodeAgentAttempt, runCodeRuntimeHeartbeatLoop, runContainerAttempt, runContainerCommand, runGoal, runHarnessRunner, runLeasedAttempt, runtimeMemoryStore, safeWorkspaceLabel, selectContainerEngine, selectWinner, sessionRecipesFor, sessionSkillsFor, stageManifests, stageWorkspace, stageWorkspacePair, straySubGoalFiles, stripPatchEnvelope, validateCodePatch, validateMemory, validateRelativePath, verifyCodeCandidate, verifyContainerEngineBoundary, withProofRecipes, withRecipeDependencies };
1699
+ /** A dependency set lent to one run, and how to give it back. */
1700
+ interface LentDependencies {
1701
+ dependencies: RecipeDependencies | null;
1702
+ /** Remove the run's clone. A no-op when nothing was cloned. */
1703
+ release(): Promise<void>;
1704
+ }
1705
+ /** Clone a directory tree, sharing blocks with the original where the filesystem can and copying otherwise. */
1706
+ declare function cloneTree(source: string, target: string, platform?: NodeJS.Platform): Promise<void>;
1707
+ /** Give one run its own writable clone of the tree when the set allows it; otherwise lend the set as it is, read-only. */
1708
+ declare function lendDependencies(dependencies: RecipeDependencies | null, runId: string): Promise<LentDependencies>;
1709
+ /** Copy the host's build output into the workspace wherever its package exists there and it has no copy of its own. Returns what was lent. */
1710
+ declare function lendBuildProducts(products: readonly LentDirectory[], workspaceDir: string): Promise<string[]>;
1711
+
1712
+ export { CODE_PATCH_PATH, CODE_RUNTIME_PROTOCOL_VERSION, type CodeAgentAttemptOptions, type CodeAgentAttemptResult, type CodeAgentRun, type CodeBuildRecipe, type CodeExpectedArtifact, type CodeLocalSourceDescriptor, type CodeMemory, type CodeMemoryEvidence, type CodeMemoryKind, type CodeMemoryStore, type CodeRecipeExecutor, type CodeRecipeResult, type CodeRuntimeAgentControlPlane, type CodeRuntimeBinding, type CodeRuntimeCandidateResponse, type CodeRuntimeCapabilities, CodeRuntimeCheckpointManager, type CodeRuntimeClientOptions, type CodeRuntimeCollaborationSkillManifest, type CodeRuntimeCollaborationToolManifest, type CodeRuntimeCollaborationToolRequest, type CodeRuntimeCommand, type CodeRuntimeCommandEngine, type CodeRuntimeCommandKind, type CodeRuntimeCommandResult, CodeRuntimeControlError, type CodeRuntimeControlPlane, type CodeRuntimeInferenceOptions, type CodeRuntimeLoopOptions, type CodeRuntimeMemory, type CodeRuntimeNewMemory, CodeRuntimeReconciler, type CodeRuntimeReviewRequest, type CodeRuntimeReviewResponse, type CodeRuntimeSnapshot, type CodeRuntimeSourceArchive, type CodeRuntimeSourceSnapshot, type CodeSkillOpts, type CodeSurface, type CodeToolBrokerOptions, type CodeToolCallRecord, type CodeToolDecision, type CodeVerificationEvidence, type CodeVerificationLog, type CodeVerificationPolicy, type ContainerEngine, type ContainerEngineSelectionOptions, type ContainerEngineVerificationOptions, type ContainerLimits, type ContainerRunOptions, type ContainerRunResult, type CreateCodeWorkspaceCheckpointInput, DEPENDENCY_INSTALL_TIMEOUT_MS, type DecomposedRun, DecompositionError, type DependencyCacheInput, type GoalAttempt, type GoalAttemptInput, type GoalAttemptOutcome, type GoalAttemptRecord, type GoalBudget, type GoalEvent, type GoalOutcome, type GoalRun, type GoalRunSpec, type GoalStoppedReason, type GoalStrategy, type HarnessRunnerOptions, type IntegrateOptions, type IntegrationStep, type LentDependencies, type LentDirectory, MAX_MEMORY_BODY, MEASURED_PREMIUM, type MaterializedCodeSource, type MaterializedGitTree, type NewCodeMemory, PROOF_RECIPE_PREFIX, type PrepareRuntimeCheckpointInput, type PreparedRuntimeCheckpoint, REPOSITORY_RECIPES_FILE, type RacedAttemptOptions, type RacedOutcome, type RecallOptions, type RecipeDependencies, type RepositoryRecipeEnvelope, type ResolvedCodeRecipes, type RestoreCodeWorkspaceCheckpointInput, type RestoredCodeWorkspaceCheckpoint, type RunCodeAgentOptions, type RuntimeCheckpointSession, SYSTEM_PROMPT_FOR, type StageWorkspaceOptions, type StagedWorkspace, type StrategyChoice, type StrategySignals, type SubGoal, type SubGoalResult, TheseusRuntimeEngine, type TheseusRuntimeEngineOptions, V1_SYSTEM_PROMPT, V2_SYSTEM_PROMPT, V3_SYSTEM_PROMPT, type VerifyCodeCandidateInput, applyCodePatch, applyPatchDialectToDiff, assertCodeBuildRecipe, assertDisjointPlan, assertLentPath, assertPinnedImage, assertReservedMount, attachCodeRuntimeReferences, buildContainerRunArgs, buildRecipeContainerArgs, chooseStrategy, cloneTree, codeSkill, createCodeRuntimeControlClient, createCodeRuntimeInference, createCodeRuntimeSessionSkillLoader, createCodeToolBroker, createCodeWorkspaceCheckpoint, createContainerRecipeExecutor, dependencyCacheKey, dependencyInstallArgs, describeCodeRecipes, describeGateFailure, describePatchFailure, digestStagedWorkspace, feedbackIsActionable, hasContextFreeHunk, hazardFromAttempt, hostBuildProducts, installedDependencies, integrateSubGoals, isCheckpointEffectCompleted, lendBuildProducts, lendDependencies, lentDirectories, materializeCodeRuntimeArchive, materializeCodeRuntimeSource, materializeCommandWorkspace, materializeGitTree, npmFailureSummary, outcomeCloses, outcomeMemory, parseRepositoryRecipes, patchPaths, pinnedNpmVersion, planReachCollisions, prepareContainerDependencies, prepareRuntimeCheckpoint, racedAttempt, readOnlyNotice, readRepositoryRecipes, recallAbout, recipeOutput, registeredFiles, renderMemories, renderOutcome, resolveCodePath, resolveCodeRecipes, restoreCodeWorkspaceCheckpoint, runCodeAgent, runCodeAgentAttempt, runCodeRuntimeHeartbeatLoop, runContainerAttempt, runContainerCommand, runGoal, runHarnessRunner, runLeasedAttempt, runtimeMemoryStore, safeWorkspaceLabel, selectContainerEngine, selectWinner, sessionRecipesFor, sessionSkillsFor, stageManifests, stageWorkspace, stageWorkspacePair, straySubGoalFiles, stripPatchEnvelope, validateCodePatch, validateMemory, validateRelativePath, verifyCodeCandidate, verifyContainerEngineBoundary, withProofRecipes, withRecipeDependencies, workspaceDirs };
package/dist/node.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  runHarnessRunner,
3
3
  runLeasedAttempt
4
- } from "./chunk-GNNAQ2JX.js";
4
+ } from "./chunk-EXSEQEZ6.js";
5
5
  import {
6
6
  CODE_PATCH_PATH,
7
7
  CODE_RUNTIME_PROTOCOL_VERSION,
@@ -19,8 +19,11 @@ import {
19
19
  applyCodePatch,
20
20
  applyPatchDialectToDiff,
21
21
  assertCodeBuildRecipe,
22
+ assertLentPath,
23
+ assertReservedMount,
22
24
  attachCodeRuntimeReferences,
23
25
  buildRecipeContainerArgs,
26
+ cloneTree,
24
27
  codeSkill,
25
28
  createCodeRuntimeControlClient,
26
29
  createCodeRuntimeInference,
@@ -34,7 +37,11 @@ import {
34
37
  digestStagedWorkspace,
35
38
  hasContextFreeHunk,
36
39
  hazardFromAttempt,
40
+ installedDependencies,
37
41
  isCheckpointEffectCompleted,
42
+ lendBuildProducts,
43
+ lendDependencies,
44
+ lentDirectories,
38
45
  materializeCodeRuntimeArchive,
39
46
  materializeCodeRuntimeSource,
40
47
  materializeCommandWorkspace,
@@ -43,6 +50,7 @@ import {
43
50
  readOnlyNotice,
44
51
  readRepositoryRecipes,
45
52
  recallAbout,
53
+ recipeOutput,
46
54
  registeredFiles,
47
55
  renderMemories,
48
56
  resolveCodePath,
@@ -60,10 +68,12 @@ import {
60
68
  validateMemory,
61
69
  validateRelativePath,
62
70
  verifyCodeCandidate,
63
- withProofRecipes
64
- } from "./chunk-4IGSN53G.js";
65
- import "./chunk-INL642J5.js";
71
+ withProofRecipes,
72
+ withRecipeDependencies
73
+ } from "./chunk-B2PQAORN.js";
74
+ import "./chunk-OXWLPB7P.js";
66
75
  import {
76
+ allowedWorkspacePath,
67
77
  assertPinnedImage,
68
78
  buildContainerRunArgs,
69
79
  materializeGitTree,
@@ -73,7 +83,7 @@ import {
73
83
  stageWorkspace,
74
84
  stageWorkspacePair,
75
85
  verifyContainerEngineBoundary
76
- } from "./chunk-ZM6AITC2.js";
86
+ } from "./chunk-3ON6UAOV.js";
77
87
  import "./chunk-T2IW7MYQ.js";
78
88
  import "./chunk-ONYW2VSB.js";
79
89
 
@@ -343,82 +353,58 @@ function chooseStrategy(signals = {}) {
343
353
  }
344
354
  var feedbackIsActionable = actionable;
345
355
 
346
- // src/code-recipe-dependencies.ts
347
- import { lstat, rm, symlink } from "fs/promises";
348
- import { isAbsolute, join } from "path";
349
- var RESERVED_MOUNTS = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
350
- function withRecipeDependencies(executor, dependencies) {
351
- const mountAs = dependencies.mountAs ?? "node_modules";
352
- if (!isAbsolute(dependencies.source)) {
353
- throw new TypeError("recipe dependency source must be an absolute path");
354
- }
355
- if (!RESERVED_MOUNTS.has(mountAs)) {
356
- throw new TypeError(`recipe dependencies must mount at a reserved name, not "${mountAs}"`);
357
- }
358
- return {
359
- run: async (input) => {
360
- const target = join(input.workspaceDir, mountAs);
361
- let linked = false;
362
- try {
363
- const existing = await lstat(target).catch(() => null);
364
- if (!existing) {
365
- await symlink(dependencies.source, target, "dir");
366
- linked = true;
367
- }
368
- return await executor.run(input);
369
- } finally {
370
- if (linked) await rm(target, { force: true, recursive: false }).catch(() => void 0);
371
- }
372
- }
373
- };
374
- }
375
- async function installedDependencies(repoRoot) {
376
- const source = join(repoRoot, "node_modules");
377
- const info = await lstat(source).catch(() => null);
378
- return info?.isDirectory() ? { source } : null;
379
- }
380
-
381
356
  // src/code-recipe-dependency-cache.ts
382
357
  import { createHash } from "crypto";
383
- import { copyFile, mkdir, readFile, readdir, rename, rm as rm2, stat, writeFile } from "fs/promises";
358
+ import { copyFile, mkdir, readFile, readdir, rename, rm, stat, writeFile } from "fs/promises";
384
359
  import { getgid, getuid } from "process";
385
- import { join as join2 } from "path";
360
+ import { join } from "path";
386
361
  var DEPENDENCY_INSTALL_TIMEOUT_MS = 20 * 6e4;
387
362
  var OUTPUT_CAP = 4 * 1024 * 1024;
363
+ var EXACT_VERSION = /^\d+\.\d+\.\d+$/;
388
364
  var exists = async (path) => Boolean(await stat(path).catch(() => null));
389
- async function dependencyCacheKey(repoRoot, image, arch = process.arch) {
390
- const lock = await readFile(join2(repoRoot, "package-lock.json")).catch(() => null);
365
+ async function pinnedNpmVersion(repoRoot) {
366
+ const manifest = await readFile(join(repoRoot, "package.json"), "utf8").catch(() => null);
367
+ if (!manifest) return null;
368
+ const engines = JSON.parse(manifest).engines;
369
+ return typeof engines?.npm === "string" && EXACT_VERSION.test(engines.npm) ? engines.npm : null;
370
+ }
371
+ async function dependencyCacheKey(repoRoot, image, arch = process.arch, npmVersion = null) {
372
+ const lock = await readFile(join(repoRoot, "package-lock.json")).catch(() => null);
391
373
  if (!lock) return null;
392
- return createHash("sha256").update(lock).update("\n").update(image).update("\n").update(arch).digest("hex").slice(0, 32);
374
+ return createHash("sha256").update(lock).update("\n").update(image).update("\n").update(arch).update("\n").update(npmVersion ?? "image").digest("hex").slice(0, 32);
375
+ }
376
+ async function workspaceDirs(repoRoot) {
377
+ const root = JSON.parse(await readFile(join(repoRoot, "package.json"), "utf8"));
378
+ const globs = Array.isArray(root.workspaces) ? root.workspaces : root.workspaces?.packages ?? [];
379
+ const dirs = [];
380
+ for (const glob of globs) {
381
+ const found = glob.endsWith("/*") ? (await readdir(join(repoRoot, glob.slice(0, -2)), { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map((entry) => `${glob.slice(0, -2)}/${entry.name}`) : [glob];
382
+ for (const dir of found) if (await exists(join(repoRoot, dir, "package.json"))) dirs.push(dir);
383
+ }
384
+ return dirs;
393
385
  }
394
386
  async function stageManifests(repoRoot, stageDir) {
395
387
  await mkdir(stageDir, { recursive: true });
396
388
  const staged = [];
397
389
  for (const name of ["package.json", "package-lock.json", ".npmrc"]) {
398
- if (!await exists(join2(repoRoot, name))) continue;
399
- await copyFile(join2(repoRoot, name), join2(stageDir, name));
390
+ if (!await exists(join(repoRoot, name))) continue;
391
+ await copyFile(join(repoRoot, name), join(stageDir, name));
400
392
  staged.push(name);
401
393
  }
402
- const root = JSON.parse(await readFile(join2(repoRoot, "package.json"), "utf8"));
403
- const globs = Array.isArray(root.workspaces) ? root.workspaces : root.workspaces?.packages ?? [];
404
- for (const glob of globs) {
405
- const dirs = glob.endsWith("/*") ? (await readdir(join2(repoRoot, glob.slice(0, -2)), { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map((entry) => `${glob.slice(0, -2)}/${entry.name}`) : [glob];
406
- for (const dir of dirs) {
407
- const manifest = join2(repoRoot, dir, "package.json");
408
- if (!await exists(manifest)) continue;
409
- await mkdir(join2(stageDir, dir), { recursive: true });
410
- await copyFile(manifest, join2(stageDir, dir, "package.json"));
411
- staged.push(`${dir}/package.json`);
412
- }
394
+ for (const dir of await workspaceDirs(repoRoot)) {
395
+ await mkdir(join(stageDir, dir), { recursive: true });
396
+ await copyFile(join(repoRoot, dir, "package.json"), join(stageDir, dir, "package.json"));
397
+ staged.push(`${dir}/package.json`);
413
398
  }
414
399
  return staged;
415
400
  }
416
- function dependencyInstallArgs(engine, image, stageDir, name) {
401
+ function dependencyInstallArgs(engine, image, stageDir, name, npmVersion = null) {
417
402
  if (/[,\r\n]/.test(stageDir)) throw new TypeError("stage path contains unsupported mount characters");
418
403
  const uid = typeof getuid === "function" ? getuid() : 1e3;
419
404
  const gid = typeof getgid === "function" ? getgid() : 1e3;
420
405
  const mount = engine === "container" ? `--mount=type=bind,source=${stageDir},target=/workspace` : `--mount=type=bind,src=${stageDir},dst=/workspace`;
421
- const npm = ["npm", "ci", "--no-audit", "--no-fund", "--ignore-scripts", "--engine-strict=false"];
406
+ const install = ["ci", "--no-audit", "--no-fund", "--ignore-scripts", "--engine-strict=false"];
407
+ const npm = npmVersion ? ["npx", "--yes", `npm@${npmVersion}`, ...install] : ["npm", ...install];
422
408
  return [
423
409
  "run",
424
410
  "--rm",
@@ -437,34 +423,79 @@ function dependencyInstallArgs(engine, image, stageDir, name) {
437
423
  ...npm
438
424
  ];
439
425
  }
426
+ function npmFailureSummary(stderr) {
427
+ const lines = stderr.split("\n").map((line) => line.trim()).filter((line) => line && line !== "npm error");
428
+ const at = lines.findIndex((line) => /^npm error code /.test(line));
429
+ return (at >= 0 ? lines.slice(at, at + 3) : lines.slice(-3)).join(" | ").slice(0, 400);
430
+ }
431
+ async function nestedTrees(treeRoot, dirs) {
432
+ const nested = [];
433
+ for (const dir of dirs) {
434
+ if (await exists(join(treeRoot, dir, "node_modules"))) nested.push({ source: join(treeRoot, dir, "node_modules"), mountAs: `${dir}/node_modules` });
435
+ }
436
+ return nested;
437
+ }
440
438
  async function prepareContainerDependencies(input) {
441
- const key = await dependencyCacheKey(input.repoRoot, input.image);
439
+ const npmVersion = await pinnedNpmVersion(input.repoRoot);
440
+ const key = await dependencyCacheKey(input.repoRoot, input.image, process.arch, npmVersion);
442
441
  if (!key) return null;
443
- const dir = join2(input.cacheRoot, key);
444
- const tree = join2(dir, "node_modules");
445
- const stage = join2(dir, "stage");
446
- if (await exists(tree)) return { source: tree };
442
+ const dir = join(input.cacheRoot, key);
443
+ const tree = join(dir, "tree");
444
+ const stage = join(dir, "stage");
445
+ const runsDir = join(dir, "runs");
446
+ await rm(runsDir, { recursive: true, force: true });
447
+ const dirs = await workspaceDirs(input.repoRoot);
448
+ const lend = async () => ({ source: join(tree, "node_modules"), nested: await nestedTrees(tree, dirs), runsDir });
449
+ if (await exists(join(tree, "node_modules"))) return lend();
447
450
  const run = input.run ?? runContainerCommand;
448
- await rm2(stage, { recursive: true, force: true });
451
+ await rm(stage, { recursive: true, force: true });
449
452
  const staged = await stageManifests(input.repoRoot, stage);
450
- input.log?.(`installing ${key.slice(0, 12)}: ${staged.length} manifests, npm ci in ${input.image}`);
453
+ input.log?.(`installing ${key.slice(0, 12)}: ${staged.length} manifests, npm${npmVersion ? `@${npmVersion}` : ""} ci in ${input.image}`);
451
454
  const name = `odla-deps-${key.slice(0, 12)}`;
452
455
  const result = await run(
453
456
  input.engine,
454
- dependencyInstallArgs(input.engine, input.image, stage, name),
457
+ dependencyInstallArgs(input.engine, input.image, stage, name, npmVersion),
455
458
  name,
456
459
  { timeoutMs: DEPENDENCY_INSTALL_TIMEOUT_MS, maxOutputBytes: OUTPUT_CAP }
457
460
  );
458
- if (result.exitCode !== 0 || result.timedOut || !await exists(join2(stage, "node_modules"))) {
459
- input.log?.(`install failed (exit ${result.exitCode}${result.timedOut ? ", timed out" : ""}): ${result.stderr.trim().split("\n").slice(-3).join(" | ").slice(0, 400)}`);
460
- await rm2(stage, { recursive: true, force: true });
461
+ if (result.exitCode !== 0 || result.timedOut || !await exists(join(stage, "node_modules"))) {
462
+ input.log?.(`install failed (exit ${result.exitCode}${result.timedOut ? ", timed out" : ""}): ${npmFailureSummary(result.stderr)}`);
463
+ await rm(stage, { recursive: true, force: true });
461
464
  return null;
462
465
  }
463
- await rename(join2(stage, "node_modules"), tree);
464
- await rm2(stage, { recursive: true, force: true });
465
- await writeFile(join2(dir, "manifest.json"), JSON.stringify({ image: input.image, key, createdAt: Date.now() }, null, 2));
466
- input.log?.(`installed ${key.slice(0, 12)} in ${Math.round(result.durationMs / 1e3)}s`);
467
- return { source: tree };
466
+ await rm(tree, { recursive: true, force: true });
467
+ await rename(stage, tree);
468
+ await writeFile(join(dir, "manifest.json"), JSON.stringify({ image: input.image, key, npmVersion, createdAt: Date.now() }, null, 2));
469
+ const lent = await lend();
470
+ input.log?.(`installed ${key.slice(0, 12)} in ${Math.round(result.durationMs / 1e3)}s, ${lent.nested?.length ?? 0} nested tree(s)`);
471
+ return lent;
472
+ }
473
+
474
+ // src/code-recipe-build-products.ts
475
+ import { spawn } from "child_process";
476
+ import { stat as stat2 } from "fs/promises";
477
+ import { join as join2 } from "path";
478
+ function gitIgnoredFiles(repoRoot) {
479
+ return new Promise((accept) => {
480
+ const child = spawn("git", ["-C", repoRoot, "ls-files", "--others", "--ignored", "--exclude-standard", "-z"], { shell: false, stdio: ["ignore", "pipe", "ignore"] });
481
+ const chunks = [];
482
+ child.stdout.on("data", (chunk) => chunks.push(chunk));
483
+ child.once("error", () => accept([]));
484
+ child.once("exit", (code) => accept(code === 0 ? Buffer.concat(chunks).toString("utf8").split("\0").filter(Boolean) : []));
485
+ });
486
+ }
487
+ async function hostBuildProducts(repoRoot) {
488
+ const dirs = await workspaceDirs(repoRoot);
489
+ const within = (path) => dirs.find((dir) => path.startsWith(`${dir}/`)) ?? ".";
490
+ const products = [];
491
+ for (const dir of dirs) {
492
+ const source = join2(repoRoot, dir, "dist");
493
+ if ((await stat2(source).catch(() => null))?.isDirectory()) products.push({ source, mountAs: `${dir}/dist`, within: dir });
494
+ }
495
+ for (const path of await gitIgnoredFiles(repoRoot)) {
496
+ if (allowedWorkspacePath(path)) products.push({ source: join2(repoRoot, path), mountAs: path, within: within(path) });
497
+ }
498
+ return products;
468
499
  }
469
500
  export {
470
501
  CODE_PATCH_PATH,
@@ -487,11 +518,14 @@ export {
487
518
  applyPatchDialectToDiff,
488
519
  assertCodeBuildRecipe,
489
520
  assertDisjointPlan,
521
+ assertLentPath,
490
522
  assertPinnedImage,
523
+ assertReservedMount,
491
524
  attachCodeRuntimeReferences,
492
525
  buildContainerRunArgs,
493
526
  buildRecipeContainerArgs,
494
527
  chooseStrategy,
528
+ cloneTree,
495
529
  codeSkill,
496
530
  createCodeRuntimeControlClient,
497
531
  createCodeRuntimeInference,
@@ -508,17 +542,23 @@ export {
508
542
  feedbackIsActionable,
509
543
  hasContextFreeHunk,
510
544
  hazardFromAttempt,
545
+ hostBuildProducts,
511
546
  installedDependencies,
512
547
  integrateSubGoals,
513
548
  isCheckpointEffectCompleted,
549
+ lendBuildProducts,
550
+ lendDependencies,
551
+ lentDirectories,
514
552
  materializeCodeRuntimeArchive,
515
553
  materializeCodeRuntimeSource,
516
554
  materializeCommandWorkspace,
517
555
  materializeGitTree,
556
+ npmFailureSummary,
518
557
  outcomeCloses,
519
558
  outcomeMemory,
520
559
  parseRepositoryRecipes,
521
560
  patchPaths,
561
+ pinnedNpmVersion,
522
562
  planReachCollisions,
523
563
  prepareContainerDependencies,
524
564
  prepareRuntimeCheckpoint,
@@ -526,6 +566,7 @@ export {
526
566
  readOnlyNotice,
527
567
  readRepositoryRecipes,
528
568
  recallAbout,
569
+ recipeOutput,
529
570
  registeredFiles,
530
571
  renderMemories,
531
572
  renderOutcome,
@@ -557,6 +598,7 @@ export {
557
598
  verifyCodeCandidate,
558
599
  verifyContainerEngineBoundary,
559
600
  withProofRecipes,
560
- withRecipeDependencies
601
+ withRecipeDependencies,
602
+ workspaceDirs
561
603
  };
562
604
  //# sourceMappingURL=node.js.map