@@ -112,6 +112,29 @@ func sharedRuntimeOwnedPaths(repo, version, sourceCommit string) (controllerPath
112112 return binary , manifest , err
113113}
114114
115+ func bootstrapRuntimePaths (repo , version , sourceCommit string ) (string , string , error ) {
116+ binary , manifest , err := bootstrapRuntimeOwnedPaths (repo , version , sourceCommit )
117+ return binary .path , manifest .path , err
118+ }
119+
120+ func bootstrapRuntimeOwnedPaths (repo , version , sourceCommit string ) (controllerPath , controllerPath , error ) {
121+ ctx := WorkspaceFor (repo )
122+ directory , err := ctx .BootstrapRuntimeDir (version , sourceCommit )
123+ if err != nil {
124+ return controllerPath {}, controllerPath {}, err
125+ }
126+ common , err := gitCommonDir (repo )
127+ if err != nil {
128+ return controllerPath {}, controllerPath {}, err
129+ }
130+ binary , err := newControllerPath (common , filepath .Join (directory , helperName ()))
131+ if err != nil {
132+ return controllerPath {}, controllerPath {}, err
133+ }
134+ manifest , err := newControllerPath (common , filepath .Join (directory , "runtime.lock.json" ))
135+ return binary , manifest , err
136+ }
137+
115138func atomicWriteMode (path string , content []byte , mode fs.FileMode ) error {
116139 directory := filepath .Dir (path )
117140 if err := os .MkdirAll (directory , 0o755 ); err != nil {
@@ -154,6 +177,31 @@ func installSharedRuntime(source, repo string, integrations map[string]Integrati
154177 return writeRuntimeSlot (source , binaryPath , manifestPath , integrations )
155178}
156179
180+ // installCommandRuntime publishes the exact runtime needed by both sides of
181+ // tracked command activation. The mode-aware shared slot is installed first so
182+ // the Git-common bootstrap is never made admissible before it can activate the
183+ // worktree-local helper. Embedded mode uses one physical slot; detached mode
184+ // deliberately uses an external shared slot plus a Git-common bootstrap slot.
185+ // control-law: tracked-launcher-selects-only-the-pinned-runtime
186+ func installCommandRuntime (source , repo string , integrations map [string ]IntegrationState ) (runtimeManifest , error ) {
187+ sharedManifest , err := installSharedRuntime (source , repo , integrations )
188+ if err != nil {
189+ return runtimeManifest {}, err
190+ }
191+ sharedBinary , _ , err := sharedRuntimePaths (repo , Version , SourceCommit )
192+ if err != nil {
193+ return runtimeManifest {}, err
194+ }
195+ bootstrapBinary , bootstrapLock , err := bootstrapRuntimeOwnedPaths (repo , Version , SourceCommit )
196+ if err != nil {
197+ return runtimeManifest {}, err
198+ }
199+ if filepath .Clean (sharedBinary ) == bootstrapBinary .path {
200+ return sharedManifest , nil
201+ }
202+ return writeRuntimeSlot (source , bootstrapBinary , bootstrapLock , integrations )
203+ }
204+
157205// installDetachedRuntime populates a detached repository's external shared-runtime
158206// slot from the running helper, so the developer-level ambient guard has a stable
159207// helper to invoke. Unlike installSharedRuntime it scopes the symlink check to the
@@ -369,7 +417,7 @@ func HydrateWorktree(repoPath string) error {
369417// this, the running binary equals the repo's committed pin by construction. The
370418// verifyGeneratedRuntime gate refuses to populate a slot for any other version,
371419// so hydration can never write a mislabeled runtime (the taxweave incident's
372- // invariant), and installSharedRuntime 's own post-write verify+rollback is the
420+ // invariant), and installCommandRuntime 's own post-write verify+rollback is the
373421// backstop. The operation is idempotent and safe under concurrent first use.
374422func RunHydrateRuntime (repoPath string ) error {
375423 repo , err := ResolveRepository (repoPath )
@@ -387,8 +435,8 @@ func RunHydrateRuntime(repoPath string) error {
387435 if err != nil {
388436 return fmt .Errorf ("load project configuration for runtime hydration: %w" , err )
389437 }
390- if _ , err := installSharedRuntime (source , repo , config .Integrations ); err != nil {
391- return fmt .Errorf ("populate the repository-family Boatstack runtime: %w" , err )
438+ if _ , err := installCommandRuntime (source , repo , config .Integrations ); err != nil {
439+ return fmt .Errorf ("populate the Boatstack command runtime: %w" , err )
392440 }
393441 return HydrateWorktree (repo )
394442}
0 commit comments