specrails-desktop 2.56.1 → 2.57.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/docs/internals/core-runtime-updates.md +6 -4
- package/docs/internals/programmatic-agent-runtime.md +2 -0
- package/package.json +1 -1
- package/server/dist/core-execution.js +49 -3
- package/server/dist/core-package.js +12 -8
- package/server/dist/core-runtime.js +4 -6
- package/server/dist/core-update-manager.js +3 -2
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +18 -0
- package/server/dist/modules/loops/runtime/loop-executors.js +3 -3
- package/server/dist/project-registry.js +2 -0
|
@@ -7,14 +7,16 @@ read-only discovery; it does not execute a PATH shim or install a global package
|
|
|
7
7
|
An explicit `SPECRAILS_CORE_BIN` wins when it resolves to a usable compatible
|
|
8
8
|
package. Otherwise Desktop selects the newest compatible package from its
|
|
9
9
|
activated managed installation, bundled resources, local dependency and external
|
|
10
|
-
CLI on PATH. Core 4
|
|
10
|
+
CLI on PATH. Supported Core majors are 4, 5 and 6 (`SUPPORTED_CORE_MAJORS` in
|
|
11
|
+
`server/core-package.ts`). A runtime older than the active
|
|
11
12
|
framework is rejected rather than silently replacing an update.
|
|
12
13
|
|
|
13
14
|
## Persistence and publication
|
|
14
15
|
|
|
15
|
-
The release bundle pins Core
|
|
16
|
-
`scripts/assemble-bundled-core.lock.json`.
|
|
17
|
-
|
|
16
|
+
The release bundle pins Core 6.0.0 in `desktop-release.yml` and
|
|
17
|
+
`scripts/assemble-bundled-core.lock.json`. Core 6 is the Desktop-only engine: it
|
|
18
|
+
publishes integration contract 5.0 (no standalone `update`) and ships only the
|
|
19
|
+
implement, batch-implement and retry workflows. Update both pins together and check compatibility against
|
|
18
20
|
the staged published package; retained runs still use their original runtime.
|
|
19
21
|
|
|
20
22
|
Desktop updates retain the complete npm installation, including dependencies,
|
|
@@ -64,6 +64,8 @@ Desktop negotiates `runtime api` and sends configuration to `runtime validate --
|
|
|
64
64
|
|
|
65
65
|
Settings are saved at `<project execution .specrails directory>/agent-runtime.json`. Missing configuration uses the default agent runtime. The retired enabled flag cannot select another engine. Malformed configuration blocks admission; it is not ignored. Saving verifies that Core exposes the expected API. Connections are stored globally in `~/.specrails/runtime-providers.json`; project files retain role references, models, limits and verification. Existing embedded connections migrate once, with stable disambiguated IDs on endpoint conflicts. New runs freeze the resolved configuration, while saved runs retain their original snapshot.
|
|
66
66
|
|
|
67
|
+
**A package of a larger checkout.** A repository registered as a subdirectory of its git checkout (for example `apps/web` inside a monorepo) is isolated in a worktree of the whole checkout, so Desktop passes that directory to Core as the repository `scope` in `desktop-context.json` (Core capability `repositoryScope`). Configured checks run inside the package: a check without `cwd`, or with a `cwd` relative to the registered directory, never runs at the checkout root, where a monorepo test script fans out to every workspace. Core keeps the change inside the scope: after each developer or fixer turn it undoes edits outside it, the reviewer judges only the git change set measured against the run's base, a check that fails for missing credentials, variables or registry access stops the run for the host instead of starting a correction round, and a correction loop that stops converging stops with the reason instead of repeating the same checks. Runs admitted before scopes existed keep their frozen whole-checkout context.
|
|
68
|
+
|
|
67
69
|
Core owns role instructions and permissions. The developer role edits and runs commands inside its CLI sandbox (the same autonomy as the legacy Implement step); architect and reviewer are read-only. A legacy rail profile/model selection does not override the runtime's per-role provider configuration. The JSON schema is [server/schemas/agent-runtime.schema.json](../../server/schemas/agent-runtime.schema.json), mirrored from Core. For a complete configuration, custom executor examples, Kimi capabilities and API tooling details, see [Core's runtime guide](https://github.com/fjpulidop/specrails-core/blob/main/docs/agent-runtime.md) in the paired revision.
|
|
68
70
|
|
|
69
71
|
The built-in Claude adapter supports its native dollar cap. Built-in Codex, Gemini, Kimi and OpenAI-compatible adapters reject `maxCostUsd`; remove that limit for mixed-provider/local runs. Kimi also rejects token caps because its usage is unavailable. Unknown cost/tokens remain unknown in accounting, rather than becoming zero. Attempt, timeout and tool limits remain available. Existing provider services, licenses and inference costs are separate from the free open-source orchestration runtime.
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkoutSubdirectory = checkoutSubdirectory;
|
|
3
4
|
exports.prepareCoreExecution = prepareCoreExecution;
|
|
4
5
|
exports.coreVerificationContext = coreVerificationContext;
|
|
5
6
|
exports.checkCoreCompletion = checkCoreCompletion;
|
|
@@ -25,6 +26,45 @@ function canonicalPath(path) {
|
|
|
25
26
|
return (0, node_path_1.join)(canonicalPath(parent), (0, node_path_1.basename)(path));
|
|
26
27
|
}
|
|
27
28
|
}
|
|
29
|
+
/** Where a directory sits inside its git checkout: '' for the checkout root or a directory outside git. */
|
|
30
|
+
function checkoutSubdirectory(directory) {
|
|
31
|
+
let start;
|
|
32
|
+
try {
|
|
33
|
+
start = (0, node_fs_1.realpathSync)(directory);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
for (let current = start;; current = (0, node_path_1.dirname)(current)) {
|
|
39
|
+
if ((0, node_fs_1.existsSync)((0, node_path_1.join)(current, '.git')))
|
|
40
|
+
return (0, node_path_1.relative)(current, start).split(node_path_1.sep).join('/');
|
|
41
|
+
if ((0, node_path_1.dirname)(current) === current)
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A registered repository may be one package of a larger git checkout (a
|
|
47
|
+
* monorepo app). An isolated worktree always mounts the whole checkout, so the
|
|
48
|
+
* registered directory travels to Core as the repository scope; otherwise Core
|
|
49
|
+
* verifies, edits and reviews every workspace of the checkout.
|
|
50
|
+
*/
|
|
51
|
+
function registeredScope(checkout, sourcePath) {
|
|
52
|
+
if (!sourcePath)
|
|
53
|
+
return undefined;
|
|
54
|
+
const prefix = checkoutSubdirectory(sourcePath);
|
|
55
|
+
// Core already receives the registered directory itself when it is not a checkout root.
|
|
56
|
+
if (!prefix || checkoutSubdirectory(checkout) !== '')
|
|
57
|
+
return undefined;
|
|
58
|
+
try {
|
|
59
|
+
return (0, node_fs_1.statSync)((0, node_path_1.join)(checkout, ...prefix.split('/'))).isDirectory() ? [prefix] : undefined;
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function withoutScope(context) {
|
|
66
|
+
return { ...context, repositories: context.repositories.map(({ scope: _scope, ...repository }) => repository) };
|
|
67
|
+
}
|
|
28
68
|
/** Stable run identity and frozen inputs are shared by every provider and retry.
|
|
29
69
|
* No cwd/global singleton: two rails in the same workspace get separate files.
|
|
30
70
|
*/
|
|
@@ -34,9 +74,13 @@ function prepareCoreExecution(input) {
|
|
|
34
74
|
throw new Error('Invalid Core execution run id');
|
|
35
75
|
const cwd = (0, node_fs_1.realpathSync)(input.cwd);
|
|
36
76
|
(0, core_update_state_1.assertWorkspaceCoreReady)(cwd);
|
|
77
|
+
const scoped = (repository, sourcePath) => {
|
|
78
|
+
const scope = registeredScope(repository.path, sourcePath);
|
|
79
|
+
return scope ? { ...repository, scope } : repository;
|
|
80
|
+
};
|
|
37
81
|
const repositories = manifest
|
|
38
|
-
? manifest.repositories.map(repo => ({ id: repo.repositoryId, name: repo.name, path: (0, node_fs_1.realpathSync)(repo.worktreePath), baseSha: repo.baseSha }))
|
|
39
|
-
: [{ id: run.repositoryId ?? (run.spec?.repositoryIds?.length === 1 ? run.spec.repositoryIds[0] : run.projectId ? `primary-${run.projectId}` : 'primary'), name: (0, node_path_1.basename)(input.repoDir ?? cwd), path: (0, node_fs_1.realpathSync)(input.repoDir ?? cwd) }];
|
|
82
|
+
? manifest.repositories.map(repo => scoped({ id: repo.repositoryId, name: repo.name, path: (0, node_fs_1.realpathSync)(repo.worktreePath), baseSha: repo.baseSha }, repo.sourcePath))
|
|
83
|
+
: [scoped({ id: run.repositoryId ?? (run.spec?.repositoryIds?.length === 1 ? run.spec.repositoryIds[0] : run.projectId ? `primary-${run.projectId}` : 'primary'), name: (0, node_path_1.basename)(input.repoDir ?? cwd), path: (0, node_fs_1.realpathSync)(input.repoDir ?? cwd) }, input.sourcePath)];
|
|
40
84
|
if (!repositories.length || repositories.some(repo => !SAFE_ID.test(repo.id)))
|
|
41
85
|
throw new Error('Invalid Core repository scope');
|
|
42
86
|
const artifactRepositoryId = manifest?.artifactRepositoryId ?? repositories[0].id;
|
|
@@ -76,7 +120,9 @@ function prepareCoreExecution(input) {
|
|
|
76
120
|
catch (error) {
|
|
77
121
|
if (error.code !== 'EEXIST')
|
|
78
122
|
throw error;
|
|
79
|
-
|
|
123
|
+
const frozen = (0, node_fs_1.readFileSync)(contextPath, 'utf8');
|
|
124
|
+
// A run admitted before repository scopes existed keeps its frozen whole-checkout context.
|
|
125
|
+
if (frozen !== serialized && frozen !== JSON.stringify(withoutScope(context), null, 2) + '\n')
|
|
80
126
|
throw new Error('Core execution context changed during an active run; start a new run for changed scope');
|
|
81
127
|
}
|
|
82
128
|
const env = { ...input.env, SPECRAILS_EXECUTION_CONTEXT: contextPath };
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CORE_PACKAGE_SPEC = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
exports.CORE_PACKAGE_SPEC = exports.SUPPORTED_CORE_MAJORS = void 0;
|
|
4
|
+
exports.isSupportedCoreVersion = isSupportedCoreVersion;
|
|
5
|
+
/** Core majors this Desktop can drive. Core 6 publishes integration contract
|
|
6
|
+
* 5.0 (no standalone `update`); Cores 4 and 5 remain readable for installed
|
|
7
|
+
* apps. The runtime resolver selects the newest usable compatible package and
|
|
8
|
+
* never downgrades a newer activated framework. */
|
|
9
|
+
exports.SUPPORTED_CORE_MAJORS = [4, 5, 6];
|
|
10
|
+
function isSupportedCoreVersion(version) {
|
|
11
|
+
return exports.SUPPORTED_CORE_MAJORS.includes(Number(version.split('.')[0]));
|
|
12
|
+
}
|
|
13
|
+
/** Online fallback selects the Core 6 lifecycle, the same major the desktop bundles. */
|
|
14
|
+
exports.CORE_PACKAGE_SPEC = 'specrails-core@^6.0.0';
|
|
@@ -15,6 +15,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
15
15
|
const path_1 = __importDefault(require("path"));
|
|
16
16
|
const artifact_registry_1 = require("./artifact-registry");
|
|
17
17
|
const bundled_core_1 = require("./bundled-core");
|
|
18
|
+
const core_package_1 = require("./core-package");
|
|
18
19
|
const semver_lite_1 = require("./semver-lite");
|
|
19
20
|
const VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
20
21
|
function managedCoreRoot(home) {
|
|
@@ -114,8 +115,8 @@ function resolveCoreRuntime(home, external) {
|
|
|
114
115
|
const runtime = packageForBinary(override, 'override');
|
|
115
116
|
if (!runtime)
|
|
116
117
|
throw new Error('SPECRAILS_CORE_BIN does not resolve to a usable specrails-core package.');
|
|
117
|
-
if (!
|
|
118
|
-
throw new Error(
|
|
118
|
+
if (!(0, core_package_1.isSupportedCoreVersion)(runtime.version))
|
|
119
|
+
throw new Error(`The explicit Core package is not compatible with this Desktop. Supported Core majors: ${core_package_1.SUPPORTED_CORE_MAJORS.join(', ')}.`);
|
|
119
120
|
if (current && (0, semver_lite_1.compareVersions)(runtime.version, current) < 0)
|
|
120
121
|
throw new Error(`The explicit Core ${runtime.version} is older than active framework ${current}; Desktop will not downgrade it.`);
|
|
121
122
|
return runtime;
|
|
@@ -135,10 +136,7 @@ function resolveCoreRuntime(home, external) {
|
|
|
135
136
|
candidates.push(managed);
|
|
136
137
|
}
|
|
137
138
|
candidates.push(...(external ?? (home === undefined ? discoverExternalCoreRuntimes() : [])));
|
|
138
|
-
const compatible = candidates.filter(candidate =>
|
|
139
|
-
const major = Number(candidate.version.split('.')[0]);
|
|
140
|
-
return major >= 4 && major <= 5;
|
|
141
|
-
}).sort((a, b) => (0, semver_lite_1.compareVersions)(b.version, a.version));
|
|
139
|
+
const compatible = candidates.filter(candidate => (0, core_package_1.isSupportedCoreVersion)(candidate.version)).sort((a, b) => (0, semver_lite_1.compareVersions)(b.version, a.version));
|
|
142
140
|
const selected = compatible[0] ?? null;
|
|
143
141
|
if (current && (!selected || (0, semver_lite_1.compareVersions)(selected.version, current) < 0)) {
|
|
144
142
|
throw new Error(`Core framework ${current} is installed, but its runtime package is unavailable. Reinstall Core ${current} or a newer compatible version; Desktop will not downgrade it.`);
|
|
@@ -13,6 +13,7 @@ const semver_lite_1 = require("./semver-lite");
|
|
|
13
13
|
const win_spawn_1 = require("./util/win-spawn");
|
|
14
14
|
const bundled_core_1 = require("./bundled-core");
|
|
15
15
|
const core_runtime_1 = require("./core-runtime");
|
|
16
|
+
const core_package_1 = require("./core-package");
|
|
16
17
|
const artifact_registry_1 = require("./artifact-registry");
|
|
17
18
|
/** Voluntary Core updates retain the complete npm package and dependencies,
|
|
18
19
|
* publish its framework, then await every project refresh. Partial refreshes
|
|
@@ -117,8 +118,8 @@ class CoreUpdateManager {
|
|
|
117
118
|
if (!requested || !(0, semver_lite_1.isValidVersion)(requested)) {
|
|
118
119
|
return { ok: false, error: 'No valid target version to update to. Check for updates first.' };
|
|
119
120
|
}
|
|
120
|
-
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(requested) || !
|
|
121
|
-
return { ok: false, error:
|
|
121
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(requested) || !(0, core_package_1.isSupportedCoreVersion)(requested)) {
|
|
122
|
+
return { ok: false, error: `This Desktop supports Core ${core_package_1.SUPPORTED_CORE_MAJORS.join(', ')}. Update Desktop before installing another major version.` };
|
|
122
123
|
}
|
|
123
124
|
const current = (0, framework_manager_1.readCurrentFrameworkVersion)(this.home);
|
|
124
125
|
if (current && !(0, semver_lite_1.isNewer)(requested, current) && !(requested === current && ((0, core_runtime_1.getCoreRuntimeStatus)(this.home).error || this.pendingVersion === requested))) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RUNTIME_HOST_ENV_KEYS = void 0;
|
|
4
4
|
exports.runtimeChangeName = runtimeChangeName;
|
|
5
|
+
exports.scopedHostChecks = scopedHostChecks;
|
|
5
6
|
exports.runAgentRuntimeInvocation = runAgentRuntimeInvocation;
|
|
6
7
|
const agent_runtime_history_1 = require("./agent-runtime-history");
|
|
7
8
|
const agent_runtime_repositories_1 = require("./agent-runtime-repositories");
|
|
@@ -20,6 +21,22 @@ const win_spawn_1 = require("../../../util/win-spawn");
|
|
|
20
21
|
function runtimeChangeName(runId) {
|
|
21
22
|
return 'runtime-' + (0, node_crypto_1.createHash)('sha256').update(runId).digest('hex').slice(0, 20);
|
|
22
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Host checks belong to the directory the user registered: for a package of a
|
|
26
|
+
* larger checkout (Core scope) they run in that package, never at the checkout
|
|
27
|
+
* root where a monorepo test script fans out to every workspace. An explicit
|
|
28
|
+
* cwd is relative to the registered directory; one already inside the scope is kept.
|
|
29
|
+
*/
|
|
30
|
+
function scopedHostChecks(checks, repositories = []) {
|
|
31
|
+
return checks.map(check => {
|
|
32
|
+
const scope = repositories.find(repository => repository.id === check.repositoryId)?.scope?.[0];
|
|
33
|
+
if (!scope || (check.cwd !== undefined && (0, node_path_1.isAbsolute)(check.cwd)))
|
|
34
|
+
return check;
|
|
35
|
+
const cwd = (check.cwd ?? '.').replace(/\\/g, '/');
|
|
36
|
+
const inside = cwd === scope || cwd.startsWith(scope + '/');
|
|
37
|
+
return { ...check, cwd: inside ? cwd : node_path_1.posix.normalize(node_path_1.posix.join(scope, cwd)) };
|
|
38
|
+
});
|
|
39
|
+
}
|
|
23
40
|
exports.RUNTIME_HOST_ENV_KEYS = [
|
|
24
41
|
'SPECRAILS_REPO_DIR', 'SPECRAILS_GIT_AUTO', 'SPECRAILS_REPO_MAP_PATH',
|
|
25
42
|
'SPECRAILS_EXECUTION_CONTEXT', 'SPECRAILS_EXECUTION_MANIFEST', 'SPECRAILS_REPOSITORIES',
|
|
@@ -61,6 +78,7 @@ async function runAgentRuntimeInvocation(options) {
|
|
|
61
78
|
const { config, origins } = (0, agent_runtime_effective_config_1.resolveEffectiveRuntimeConfig)((0, agent_runtime_settings_1.loadRuntimeConfigFile)(options.configPath, options.defaultProvider), {
|
|
62
79
|
repositoryIds: admittedContext.repositories.map(repo => repo.id), source, providerOverride: options.providerOverride,
|
|
63
80
|
});
|
|
81
|
+
config.verification = scopedHostChecks(config.verification, admittedContext.repositories);
|
|
64
82
|
config.rolePrompts = { ...(await (0, agent_runtime_loader_1.loadCoreAgentRuntime)()).rolePromptDefaults(), ...(0, agent_runtime_settings_1.loadRuntimeRolePrompts)() };
|
|
65
83
|
// Core rejects unknown connection keys: drop the desktop-only local-engine
|
|
66
84
|
// fields (label/defaultModel/rates/supportsReasoningEffort) before Core sees it.
|
|
@@ -237,7 +237,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
237
237
|
const existingContext = coreRun ? runtimeContextPath(cwd, coreRun.runId, baseEnv) : undefined;
|
|
238
238
|
const programmatic = coreRun && existingContext && (coreRun.implementation || (coreRun.verificationStep && existsRuntimeRequest(existingContext)));
|
|
239
239
|
const baseStepEnv = programmatic ? programmaticStepEnv(baseEnv, repoDir, executionManifest) : withProfileEnv(aiStepEnv(baseEnv, repoDir, executionManifest), provider, profileName);
|
|
240
|
-
const core = coreRun ? (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv }) : undefined;
|
|
240
|
+
const core = coreRun ? (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv, sourcePath: executionManifest ? undefined : opts.sourcePath?.() }) : undefined;
|
|
241
241
|
const stepEnv = core?.env ?? baseStepEnv;
|
|
242
242
|
if (coreRun?.implementation && core) {
|
|
243
243
|
completionContexts.set(coreRun.runId, { cwd, contextPath: core.contextPath, env: stepEnv, runId: coreRun.runId });
|
|
@@ -476,7 +476,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
476
476
|
if (!adapter.capabilities.persistentStdin)
|
|
477
477
|
return null;
|
|
478
478
|
const baseStepEnv = withProfileEnv(aiStepEnv(resolveEnv(), repoDir, executionManifest), provider, profileName);
|
|
479
|
-
const core = coreRun ? (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv }) : undefined;
|
|
479
|
+
const core = coreRun ? (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv, sourcePath: executionManifest ? undefined : opts.sourcePath?.() }) : undefined;
|
|
480
480
|
const stepEnv = core?.env ?? baseStepEnv;
|
|
481
481
|
const extraArgs = aiStepExtraArgs(adapter, cwd, repoDir, executionManifest);
|
|
482
482
|
if (repoDir) {
|
|
@@ -532,7 +532,7 @@ function createLoopExecutors(opts = {}) {
|
|
|
532
532
|
const baseEnv = resolveEnv();
|
|
533
533
|
const programmatic = existsRuntimeRequest(runtimeContextPath(cwd, coreRun.runId, baseEnv));
|
|
534
534
|
const baseStepEnv = programmatic ? programmaticStepEnv(baseEnv, repoDir, executionManifest) : withProfileEnv(aiStepEnv(baseEnv, repoDir, executionManifest), provider, profileName);
|
|
535
|
-
const core = (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv });
|
|
535
|
+
const core = (0, core_execution_1.prepareCoreExecution)({ run: coreRun, cwd, repoDir, manifest: executionManifest, env: baseStepEnv, sourcePath: executionManifest ? undefined : opts.sourcePath?.() });
|
|
536
536
|
if (existsRuntimeRequest(core.contextPath))
|
|
537
537
|
return (0, core_execution_1.checkCoreCompletion)(core.contextPath, cwd, { ...programmaticStepEnv(resolveEnv(), repoDir, executionManifest), SPECRAILS_EXECUTION_CONTEXT: core.contextPath }, coreRun.runId);
|
|
538
538
|
const env = (0, runtime_1.buildProviderEnv)((0, providers_1.getAdapter)(provider), { prompt: '', model, reasoning_effort: effort }, core.env);
|
|
@@ -1106,6 +1106,8 @@ class ProjectRegistry {
|
|
|
1106
1106
|
// See resolveLoopBaseEnv.
|
|
1107
1107
|
const loopRunManager = new loop_run_manager_1.LoopRunManager(db, boundBroadcast, (0, loop_executors_1.createLoopExecutors)({
|
|
1108
1108
|
pluginScope: () => ({ stateRoot: (0, workspace_resolution_1.resolveProjectExecution)(project).cwd, legacyProviderId: project.provider }),
|
|
1109
|
+
// A project registered as a package of a larger checkout scopes Core to that package in isolated worktrees.
|
|
1110
|
+
sourcePath: () => project.path,
|
|
1109
1111
|
env: () => (0, workspace_resolution_1.resolveLoopBaseEnv)({ slug: project.slug, path: project.path }, undefined, (0, project_env_1.applyWorktreeEnvPassthrough)(db, process.env)),
|
|
1110
1112
|
// Named rail profiles and global per-agent defaults ride the same
|
|
1111
1113
|
// SPECRAILS_PROFILE_PATH snapshot in both AI transports. An explicit null
|