feat(cmdline): hand the launcher's remaining arguments to the app it boots
A launcher provides three values before the tree mounts: ctx.cmdlineArgs (get() is the whole interface) carrying everything after its own flags, ctx.appExit for a bounded exit, and ctx.appPatches for decisions a later recomposition must keep. An app's startup row injects cmdlineArgs and calls runStartup() with its own commander program. Rows the app configures inject its startup service, so they wait until the startup row has resolved their values and provided it; --help prints, disables those rows, and exits without the app ever starting. A changed row is recycled — disabled, then re-enabled with its new values — because a row's config is resolved when the Loader creates its fiber, while the row is still waiting. Recycling never touches inject: an inject update restarts the row from its unwrapped callback and loses the plugin's own static injections. A mount still in flight is allowed to settle first, so the disable has a fiber to dispose instead of racing one into existence.
This commit is contained in:
34
packages/boot/cmdline/src/invariant.ts
Normal file
34
packages/boot/cmdline/src/invariant.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Package-owned invariant companion for `@deepseek-ai/dsh-cmdline`.
|
||||
* @module @deepseek-ai/dsh-cmdline/invariant
|
||||
*/
|
||||
|
||||
import type { Context } from 'cordis'
|
||||
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-cmdline'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'cmdline-invariant'
|
||||
/** Service required before the companion can register. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
/**
|
||||
* No runtime invariant: the owned relation is "no row is left waiting for a
|
||||
* startup service", which is a property of the whole tree at Loader
|
||||
* settlement, and the invariant service carries no settlement signal to
|
||||
* evaluate it at. Observing it from the entry stream would fire while startup
|
||||
* is still parsing, when every waiting row is legitimately still waiting. The
|
||||
* launcher's post-settlement audit (`assertEntriesActivated`) already reports
|
||||
* a startup service that was never provided as a pending entry naming it, and
|
||||
* the built-bin e2e asserts the apps boot with flag values applied.
|
||||
*/
|
||||
const install: InvariantInstaller = () => {}
|
||||
|
||||
/**
|
||||
* Register this package's invariant companion.
|
||||
* @param ctx - Cordis context carrying the invariant service.
|
||||
* @returns the installed registration's disposer after setup succeeds.
|
||||
*/
|
||||
export const apply = (ctx: Context): Promise<() => void> =>
|
||||
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
|
||||
Reference in New Issue
Block a user