opensip-cli 0.1.0
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/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +51 -0
- package/dist/api.d.ts +17 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +16 -0
- package/dist/api.js.map +1 -0
- package/dist/bootstrap/admit-tool-package.d.ts +117 -0
- package/dist/bootstrap/admit-tool-package.d.ts.map +1 -0
- package/dist/bootstrap/admit-tool-package.js +170 -0
- package/dist/bootstrap/admit-tool-package.js.map +1 -0
- package/dist/bootstrap/baseline-seams.d.ts +30 -0
- package/dist/bootstrap/baseline-seams.d.ts.map +1 -0
- package/dist/bootstrap/baseline-seams.js +156 -0
- package/dist/bootstrap/baseline-seams.js.map +1 -0
- package/dist/bootstrap/bootstrap-error.d.ts +41 -0
- package/dist/bootstrap/bootstrap-error.d.ts.map +1 -0
- package/dist/bootstrap/bootstrap-error.js +33 -0
- package/dist/bootstrap/bootstrap-error.js.map +1 -0
- package/dist/bootstrap/build-command-registration-input.d.ts +34 -0
- package/dist/bootstrap/build-command-registration-input.d.ts.map +1 -0
- package/dist/bootstrap/build-command-registration-input.js +73 -0
- package/dist/bootstrap/build-command-registration-input.js.map +1 -0
- package/dist/bootstrap/build-per-run-scope.d.ts +62 -0
- package/dist/bootstrap/build-per-run-scope.d.ts.map +1 -0
- package/dist/bootstrap/build-per-run-scope.js +152 -0
- package/dist/bootstrap/build-per-run-scope.js.map +1 -0
- package/dist/bootstrap/build-targets.d.ts +42 -0
- package/dist/bootstrap/build-targets.d.ts.map +1 -0
- package/dist/bootstrap/build-targets.js +117 -0
- package/dist/bootstrap/build-targets.js.map +1 -0
- package/dist/bootstrap/cli-defaults.d.ts +35 -0
- package/dist/bootstrap/cli-defaults.d.ts.map +1 -0
- package/dist/bootstrap/cli-defaults.js +65 -0
- package/dist/bootstrap/cli-defaults.js.map +1 -0
- package/dist/bootstrap/config-and-capabilities.d.ts +74 -0
- package/dist/bootstrap/config-and-capabilities.d.ts.map +1 -0
- package/dist/bootstrap/config-and-capabilities.js +224 -0
- package/dist/bootstrap/config-and-capabilities.js.map +1 -0
- package/dist/bootstrap/deliver-envelope.d.ts +80 -0
- package/dist/bootstrap/deliver-envelope.d.ts.map +1 -0
- package/dist/bootstrap/deliver-envelope.js +195 -0
- package/dist/bootstrap/deliver-envelope.js.map +1 -0
- package/dist/bootstrap/egress-plane.d.ts +22 -0
- package/dist/bootstrap/egress-plane.d.ts.map +1 -0
- package/dist/bootstrap/egress-plane.js +37 -0
- package/dist/bootstrap/egress-plane.js.map +1 -0
- package/dist/bootstrap/host-planes.d.ts +28 -0
- package/dist/bootstrap/host-planes.d.ts.map +1 -0
- package/dist/bootstrap/host-planes.js +152 -0
- package/dist/bootstrap/host-planes.js.map +1 -0
- package/dist/bootstrap/index.d.ts +76 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +109 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/bootstrap/live-plane.d.ts +51 -0
- package/dist/bootstrap/live-plane.d.ts.map +1 -0
- package/dist/bootstrap/live-plane.js +72 -0
- package/dist/bootstrap/live-plane.js.map +1 -0
- package/dist/bootstrap/load-tool-capabilities.d.ts +42 -0
- package/dist/bootstrap/load-tool-capabilities.d.ts.map +1 -0
- package/dist/bootstrap/load-tool-capabilities.js +76 -0
- package/dist/bootstrap/load-tool-capabilities.js.map +1 -0
- package/dist/bootstrap/output-plane.d.ts +37 -0
- package/dist/bootstrap/output-plane.d.ts.map +1 -0
- package/dist/bootstrap/output-plane.js +114 -0
- package/dist/bootstrap/output-plane.js.map +1 -0
- package/dist/bootstrap/owning-tool-init.d.ts +32 -0
- package/dist/bootstrap/owning-tool-init.d.ts.map +1 -0
- package/dist/bootstrap/owning-tool-init.js +69 -0
- package/dist/bootstrap/owning-tool-init.js.map +1 -0
- package/dist/bootstrap/pre-action-guards.d.ts +44 -0
- package/dist/bootstrap/pre-action-guards.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-guards.js +136 -0
- package/dist/bootstrap/pre-action-guards.js.map +1 -0
- package/dist/bootstrap/pre-action-hook.d.ts +68 -0
- package/dist/bootstrap/pre-action-hook.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-hook.js +289 -0
- package/dist/bootstrap/pre-action-hook.js.map +1 -0
- package/dist/bootstrap/pre-action-messages.d.ts +32 -0
- package/dist/bootstrap/pre-action-messages.d.ts.map +1 -0
- package/dist/bootstrap/pre-action-messages.js +49 -0
- package/dist/bootstrap/pre-action-messages.js.map +1 -0
- package/dist/bootstrap/process-idempotency.d.ts +17 -0
- package/dist/bootstrap/process-idempotency.d.ts.map +1 -0
- package/dist/bootstrap/process-idempotency.js +20 -0
- package/dist/bootstrap/process-idempotency.js.map +1 -0
- package/dist/bootstrap/register-language-adapters.d.ts +23 -0
- package/dist/bootstrap/register-language-adapters.d.ts.map +1 -0
- package/dist/bootstrap/register-language-adapters.js +35 -0
- package/dist/bootstrap/register-language-adapters.js.map +1 -0
- package/dist/bootstrap/register-tools.d.ts +228 -0
- package/dist/bootstrap/register-tools.d.ts.map +1 -0
- package/dist/bootstrap/register-tools.js +696 -0
- package/dist/bootstrap/register-tools.js.map +1 -0
- package/dist/bootstrap/render.d.ts +27 -0
- package/dist/bootstrap/render.d.ts.map +1 -0
- package/dist/bootstrap/render.js +53 -0
- package/dist/bootstrap/render.js.map +1 -0
- package/dist/bootstrap/report.d.ts +34 -0
- package/dist/bootstrap/report.d.ts.map +1 -0
- package/dist/bootstrap/report.js +47 -0
- package/dist/bootstrap/report.js.map +1 -0
- package/dist/bootstrap/run-plane.d.ts +105 -0
- package/dist/bootstrap/run-plane.d.ts.map +1 -0
- package/dist/bootstrap/run-plane.js +190 -0
- package/dist/bootstrap/run-plane.js.map +1 -0
- package/dist/bootstrap/scope-access.d.ts +68 -0
- package/dist/bootstrap/scope-access.d.ts.map +1 -0
- package/dist/bootstrap/scope-access.js +115 -0
- package/dist/bootstrap/scope-access.js.map +1 -0
- package/dist/bootstrap/state-seams.d.ts +14 -0
- package/dist/bootstrap/state-seams.d.ts.map +1 -0
- package/dist/bootstrap/state-seams.js +26 -0
- package/dist/bootstrap/state-seams.js.map +1 -0
- package/dist/bootstrap/tool-lifecycle.d.ts +102 -0
- package/dist/bootstrap/tool-lifecycle.d.ts.map +1 -0
- package/dist/bootstrap/tool-lifecycle.js +103 -0
- package/dist/bootstrap/tool-lifecycle.js.map +1 -0
- package/dist/bootstrap/tool-trust.d.ts +49 -0
- package/dist/bootstrap/tool-trust.d.ts.map +1 -0
- package/dist/bootstrap/tool-trust.js +65 -0
- package/dist/bootstrap/tool-trust.js.map +1 -0
- package/dist/bootstrap/validate-tool.d.ts +22 -0
- package/dist/bootstrap/validate-tool.d.ts.map +1 -0
- package/dist/bootstrap/validate-tool.js +38 -0
- package/dist/bootstrap/validate-tool.js.map +1 -0
- package/dist/cli-context.d.ts +38 -0
- package/dist/cli-context.d.ts.map +1 -0
- package/dist/cli-context.js +134 -0
- package/dist/cli-context.js.map +1 -0
- package/dist/commands/agent-catalog.d.ts +45 -0
- package/dist/commands/agent-catalog.d.ts.map +1 -0
- package/dist/commands/agent-catalog.js +115 -0
- package/dist/commands/agent-catalog.js.map +1 -0
- package/dist/commands/assemble-outcome.d.ts +69 -0
- package/dist/commands/assemble-outcome.d.ts.map +1 -0
- package/dist/commands/assemble-outcome.js +121 -0
- package/dist/commands/assemble-outcome.js.map +1 -0
- package/dist/commands/clear.d.ts +32 -0
- package/dist/commands/clear.d.ts.map +1 -0
- package/dist/commands/clear.js +73 -0
- package/dist/commands/clear.js.map +1 -0
- package/dist/commands/completion.d.ts +90 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +233 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/configure.d.ts +32 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +94 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/history.d.ts +18 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +48 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/host-command-specs.d.ts +49 -0
- package/dist/commands/host-command-specs.d.ts.map +1 -0
- package/dist/commands/host-command-specs.js +331 -0
- package/dist/commands/host-command-specs.js.map +1 -0
- package/dist/commands/host-subcommand-groups.d.ts +69 -0
- package/dist/commands/host-subcommand-groups.d.ts.map +1 -0
- package/dist/commands/host-subcommand-groups.js +374 -0
- package/dist/commands/host-subcommand-groups.js.map +1 -0
- package/dist/commands/index.d.ts +36 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +36 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init/config-templates.d.ts +16 -0
- package/dist/commands/init/config-templates.d.ts.map +1 -0
- package/dist/commands/init/config-templates.js +108 -0
- package/dist/commands/init/config-templates.js.map +1 -0
- package/dist/commands/init/file-classifier.d.ts +40 -0
- package/dist/commands/init/file-classifier.d.ts.map +1 -0
- package/dist/commands/init/file-classifier.js +155 -0
- package/dist/commands/init/file-classifier.js.map +1 -0
- package/dist/commands/init/language-detection.d.ts +44 -0
- package/dist/commands/init/language-detection.d.ts.map +1 -0
- package/dist/commands/init/language-detection.js +124 -0
- package/dist/commands/init/language-detection.js.map +1 -0
- package/dist/commands/init/scaffold-writer.d.ts +26 -0
- package/dist/commands/init/scaffold-writer.d.ts.map +1 -0
- package/dist/commands/init/scaffold-writer.js +102 -0
- package/dist/commands/init/scaffold-writer.js.map +1 -0
- package/dist/commands/init/state-machine.d.ts +32 -0
- package/dist/commands/init/state-machine.d.ts.map +1 -0
- package/dist/commands/init/state-machine.js +105 -0
- package/dist/commands/init/state-machine.js.map +1 -0
- package/dist/commands/init.d.ts +95 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +209 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mount-command-spec.d.ts +106 -0
- package/dist/commands/mount-command-spec.d.ts.map +1 -0
- package/dist/commands/mount-command-spec.js +313 -0
- package/dist/commands/mount-command-spec.js.map +1 -0
- package/dist/commands/mount-result-command.d.ts +71 -0
- package/dist/commands/mount-result-command.d.ts.map +1 -0
- package/dist/commands/mount-result-command.js +76 -0
- package/dist/commands/mount-result-command.js.map +1 -0
- package/dist/commands/plugin/config-edit.d.ts +20 -0
- package/dist/commands/plugin/config-edit.d.ts.map +1 -0
- package/dist/commands/plugin/config-edit.js +102 -0
- package/dist/commands/plugin/config-edit.js.map +1 -0
- package/dist/commands/plugin/domain-resolution.d.ts +38 -0
- package/dist/commands/plugin/domain-resolution.d.ts.map +1 -0
- package/dist/commands/plugin/domain-resolution.js +98 -0
- package/dist/commands/plugin/domain-resolution.js.map +1 -0
- package/dist/commands/plugin/host-dir.d.ts +42 -0
- package/dist/commands/plugin/host-dir.d.ts.map +1 -0
- package/dist/commands/plugin/host-dir.js +168 -0
- package/dist/commands/plugin/host-dir.js.map +1 -0
- package/dist/commands/plugin-host-ops.d.ts +41 -0
- package/dist/commands/plugin-host-ops.d.ts.map +1 -0
- package/dist/commands/plugin-host-ops.js +114 -0
- package/dist/commands/plugin-host-ops.js.map +1 -0
- package/dist/commands/plugin.d.ts +81 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +287 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/render-outcome.d.ts +52 -0
- package/dist/commands/render-outcome.d.ts.map +1 -0
- package/dist/commands/render-outcome.js +55 -0
- package/dist/commands/render-outcome.js.map +1 -0
- package/dist/commands/session-show.d.ts +27 -0
- package/dist/commands/session-show.d.ts.map +1 -0
- package/dist/commands/session-show.js +166 -0
- package/dist/commands/session-show.js.map +1 -0
- package/dist/commands/shared.d.ts +107 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +13 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/tools/data-purge.d.ts +20 -0
- package/dist/commands/tools/data-purge.d.ts.map +1 -0
- package/dist/commands/tools/data-purge.js +59 -0
- package/dist/commands/tools/data-purge.js.map +1 -0
- package/dist/commands/tools/index.d.ts +16 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +213 -0
- package/dist/commands/tools/index.js.map +1 -0
- package/dist/commands/tools/install.d.ts +24 -0
- package/dist/commands/tools/install.d.ts.map +1 -0
- package/dist/commands/tools/install.js +83 -0
- package/dist/commands/tools/install.js.map +1 -0
- package/dist/commands/tools/list.d.ts +41 -0
- package/dist/commands/tools/list.d.ts.map +1 -0
- package/dist/commands/tools/list.js +103 -0
- package/dist/commands/tools/list.js.map +1 -0
- package/dist/commands/tools/runtime-probe-entry.d.ts +14 -0
- package/dist/commands/tools/runtime-probe-entry.d.ts.map +1 -0
- package/dist/commands/tools/runtime-probe-entry.js +36 -0
- package/dist/commands/tools/runtime-probe-entry.js.map +1 -0
- package/dist/commands/tools/runtime-probe.d.ts +29 -0
- package/dist/commands/tools/runtime-probe.d.ts.map +1 -0
- package/dist/commands/tools/runtime-probe.js +66 -0
- package/dist/commands/tools/runtime-probe.js.map +1 -0
- package/dist/commands/tools/storage-contract-checks.d.ts +37 -0
- package/dist/commands/tools/storage-contract-checks.d.ts.map +1 -0
- package/dist/commands/tools/storage-contract-checks.js +91 -0
- package/dist/commands/tools/storage-contract-checks.js.map +1 -0
- package/dist/commands/tools/uninstall.d.ts +29 -0
- package/dist/commands/tools/uninstall.d.ts.map +1 -0
- package/dist/commands/tools/uninstall.js +77 -0
- package/dist/commands/tools/uninstall.js.map +1 -0
- package/dist/commands/tools/validate.d.ts +44 -0
- package/dist/commands/tools/validate.d.ts.map +1 -0
- package/dist/commands/tools/validate.js +202 -0
- package/dist/commands/tools/validate.js.map +1 -0
- package/dist/commands/uninstall/targets.d.ts +53 -0
- package/dist/commands/uninstall/targets.d.ts.map +1 -0
- package/dist/commands/uninstall/targets.js +205 -0
- package/dist/commands/uninstall/targets.js.map +1 -0
- package/dist/commands/uninstall.d.ts +88 -0
- package/dist/commands/uninstall.d.ts.map +1 -0
- package/dist/commands/uninstall.js +184 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/env/host-env-specs.d.ts +52 -0
- package/dist/env/host-env-specs.d.ts.map +1 -0
- package/dist/env/host-env-specs.js +129 -0
- package/dist/env/host-env-specs.js.map +1 -0
- package/dist/error-handler.d.ts +64 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +180 -0
- package/dist/error-handler.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/dist/open-report.d.ts +40 -0
- package/dist/open-report.d.ts.map +1 -0
- package/dist/open-report.js +54 -0
- package/dist/open-report.js.map +1 -0
- package/dist/report-compose.d.ts +35 -0
- package/dist/report-compose.d.ts.map +1 -0
- package/dist/report-compose.js +103 -0
- package/dist/report-compose.js.map +1 -0
- package/dist/session-replay-registry.d.ts +20 -0
- package/dist/session-replay-registry.d.ts.map +1 -0
- package/dist/session-replay-registry.js +38 -0
- package/dist/session-replay-registry.js.map +1 -0
- package/dist/telemetry/profiling.d.ts +42 -0
- package/dist/telemetry/profiling.d.ts.map +1 -0
- package/dist/telemetry/profiling.js +160 -0
- package/dist/telemetry/profiling.js.map +1 -0
- package/dist/telemetry/sdk-init.d.ts +87 -0
- package/dist/telemetry/sdk-init.d.ts.map +1 -0
- package/dist/telemetry/sdk-init.js +235 -0
- package/dist/telemetry/sdk-init.js.map +1 -0
- package/dist/ui/App.d.ts +32 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +35 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/render.d.ts +15 -0
- package/dist/ui/render.d.ts.map +1 -0
- package/dist/ui/render.js +21 -0
- package/dist/ui/render.js.map +1 -0
- package/dist/ui/result-to-view.d.ts +40 -0
- package/dist/ui/result-to-view.d.ts.map +1 -0
- package/dist/ui/result-to-view.js +389 -0
- package/dist/ui/result-to-view.js.map +1 -0
- package/dist/ui/views/init-view.d.ts +9 -0
- package/dist/ui/views/init-view.d.ts.map +1 -0
- package/dist/ui/views/init-view.js +119 -0
- package/dist/ui/views/init-view.js.map +1 -0
- package/dist/ui/views/misc-views.d.ts +18 -0
- package/dist/ui/views/misc-views.d.ts.map +1 -0
- package/dist/ui/views/misc-views.js +244 -0
- package/dist/ui/views/misc-views.js.map +1 -0
- package/dist/ui/views/plugin-view.d.ts +8 -0
- package/dist/ui/views/plugin-view.d.ts.map +1 -0
- package/dist/ui/views/plugin-view.js +135 -0
- package/dist/ui/views/plugin-view.js.map +1 -0
- package/dist/ui/views/tools-views.d.ts +12 -0
- package/dist/ui/views/tools-views.d.ts.map +1 -0
- package/dist/ui/views/tools-views.js +152 -0
- package/dist/ui/views/tools-views.js.map +1 -0
- package/dist/update-notifier.d.ts +108 -0
- package/dist/update-notifier.d.ts.map +1 -0
- package/dist/update-notifier.js +188 -0
- package/dist/update-notifier.js.map +1 -0
- package/dist/update-state.d.ts +40 -0
- package/dist/update-state.d.ts.map +1 -0
- package/dist/update-state.js +81 -0
- package/dist/update-state.js.map +1 -0
- package/dist/welcome.d.ts +53 -0
- package/dist/welcome.d.ts.map +1 -0
- package/dist/welcome.js +89 -0
- package/dist/welcome.js.map +1 -0
- package/package.json +100 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* owning-tool-init — resolve the tool that owns the invoked subcommand and run
|
|
3
|
+
* its lazy, once-per-process `Tool.initialize()`.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `pre-action-hook.ts` so that hook stays the high-level
|
|
6
|
+
* per-invocation SEQUENCER; the owning-tool resolution + fail-fast init
|
|
7
|
+
* semantics live here as a cohesive unit (see also `tool-lifecycle.ts`).
|
|
8
|
+
*/
|
|
9
|
+
import { logger } from '@opensip-cli/core';
|
|
10
|
+
import { BootstrapError } from './bootstrap-error.js';
|
|
11
|
+
import { initializedToolIds } from './process-idempotency.js';
|
|
12
|
+
const MODULE_TAG = 'cli:bootstrap';
|
|
13
|
+
/**
|
|
14
|
+
* Find the registered tool that owns the invoked subcommand, matching the
|
|
15
|
+
* descriptor's canonical name or any alias. Returns undefined for
|
|
16
|
+
* CLI-only commands (init/sessions/configure/plugin/...) — they belong to
|
|
17
|
+
* no tool, so no `initialize()` runs for them.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveOwningTool(tools, cmdName) {
|
|
20
|
+
return tools
|
|
21
|
+
.list()
|
|
22
|
+
.find((tool) => tool.commands.some((c) => c.name === cmdName || (c.aliases?.includes(cmdName) ?? false)));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Lazy, memoized Tool.initialize() (P1a). Resolve the tool owning the
|
|
26
|
+
* invoked subcommand and run its initialize() exactly once per process,
|
|
27
|
+
* after the scope is entered and immediately before the action body. Tools
|
|
28
|
+
* not invoked this run pay nothing; `--help`/welcome run no initialize().
|
|
29
|
+
*
|
|
30
|
+
* Fail-fast: a throwing initialize() fails the run closed rather than letting a
|
|
31
|
+
* half-initialised tool run its command and silently appear to work. The
|
|
32
|
+
* id is recorded only on success, so a transient failure can retry in a
|
|
33
|
+
* long-lived host.
|
|
34
|
+
*
|
|
35
|
+
* @throws {BootstrapError} (exit 1) when the owning tool's initialize() throws —
|
|
36
|
+
* the top-level boundary renders it (human stderr / structured `--json`).
|
|
37
|
+
*/
|
|
38
|
+
export async function maybeInitializeOwningTool(tools, cmdName, runId) {
|
|
39
|
+
const owningTool = resolveOwningTool(tools, cmdName);
|
|
40
|
+
if (!owningTool?.initialize)
|
|
41
|
+
return;
|
|
42
|
+
const toolHumanId = owningTool.metadata.name ?? owningTool.metadata.id;
|
|
43
|
+
if (initializedToolIds.has(toolHumanId))
|
|
44
|
+
return;
|
|
45
|
+
try {
|
|
46
|
+
await owningTool.initialize();
|
|
47
|
+
initializedToolIds.add(toolHumanId);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
51
|
+
logger.error({
|
|
52
|
+
evt: 'cli.tool.initialize_failed',
|
|
53
|
+
module: MODULE_TAG,
|
|
54
|
+
runId,
|
|
55
|
+
toolId: owningTool.metadata.id, // stable UUID for structured
|
|
56
|
+
toolName: toolHumanId,
|
|
57
|
+
error: msg,
|
|
58
|
+
});
|
|
59
|
+
// §4.7: a tool-init failure becomes a typed BootstrapError (exit 1) the
|
|
60
|
+
// top-level boundary renders, instead of an inline stderr write + exit.
|
|
61
|
+
throw new BootstrapError({
|
|
62
|
+
message: `Tool '${toolHumanId}' failed to initialize: ${msg}`,
|
|
63
|
+
humanMessage: `✗ Tool '${toolHumanId}' failed to initialize: ${msg}`,
|
|
64
|
+
suggestion: undefined,
|
|
65
|
+
exitCode: 1,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=owning-tool-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owning-tool-init.js","sourceRoot":"","sources":["../../src/bootstrap/owning-tool-init.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAgC,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,UAAU,GAAG,eAAe,CAAC;AAEnC;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAmB,EAAE,OAAe;IACpE,OAAO,KAAK;SACT,IAAI,EAAE;SACN,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CACb,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CACzF,CAAC;AACN,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,KAAmB,EACnB,OAAe,EACf,KAAa;IAEb,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,EAAE,UAAU;QAAE,OAAO;IACpC,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;IACvE,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC;QAAE,OAAO;IAChD,IAAI,CAAC;QACH,MAAM,UAAU,CAAC,UAAU,EAAE,CAAC;QAC9B,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC;YACX,GAAG,EAAE,4BAA4B;YACjC,MAAM,EAAE,UAAU;YAClB,KAAK;YACL,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,EAAE,6BAA6B;YAC7D,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,GAAG;SACX,CAAC,CAAC;QACH,wEAAwE;QACxE,wEAAwE;QACxE,MAAM,IAAI,cAAc,CAAC;YACvB,OAAO,EAAE,SAAS,WAAW,2BAA2B,GAAG,EAAE;YAC7D,YAAY,EAAE,WAAW,WAAW,2BAA2B,GAAG,EAAE;YACpE,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pre-action-guards — the pure bailout / warning guards the bootstrap
|
|
3
|
+
* `preAction` hook runs inside its decision window, BEFORE any side effect
|
|
4
|
+
* fires (see `pre-action-hook.ts` for the load-bearing ordering).
|
|
5
|
+
*
|
|
6
|
+
* Extracted from `pre-action-hook.ts` as a cohesive unit: each guard is a
|
|
7
|
+
* `(project, …) => void` that either exits the process with an actionable
|
|
8
|
+
* message (schema-too-old, no-project) or warns to stderr (phantom runtimes),
|
|
9
|
+
* and nothing else. Housing them here keeps the hook module focused on the
|
|
10
|
+
* orchestration sequence and the per-tool `initialize()` lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
import { type ProjectContext } from '@opensip-cli/core';
|
|
13
|
+
/**
|
|
14
|
+
* Schema-version bailout. THROWS a {@link BootstrapError} (exit 2) with the
|
|
15
|
+
* "upgrade your CLI" message when the project config declares a schema newer than
|
|
16
|
+
* this CLI knows. Direction-correct: `migrate` would go the other way (old → new);
|
|
17
|
+
* when the CLI itself is behind, the user must upgrade it. The top-level boundary
|
|
18
|
+
* renders it (human stderr / structured `--json`); this guard no longer writes or
|
|
19
|
+
* exits (§4.7).
|
|
20
|
+
*
|
|
21
|
+
* @throws {BootstrapError} (exit 2) when the project config's schema is newer than
|
|
22
|
+
* this CLI supports — the boundary renders the "upgrade your CLI" message.
|
|
23
|
+
*/
|
|
24
|
+
export declare function checkSchemaVersionAndBailout(project: ProjectContext, runId: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* No-project-found bailout. THROWS a {@link BootstrapError} (exit 2) for
|
|
27
|
+
* project-scoped commands when discovery resolved scope === 'none'. The top-level
|
|
28
|
+
* boundary renders it: human mode writes the unchanged multi-line explainer to
|
|
29
|
+
* stderr; `--json` emits a structured `bootstrap.error` outcome (§4.7). The guard
|
|
30
|
+
* no longer branches on json or writes a stream itself.
|
|
31
|
+
*
|
|
32
|
+
* @throws {BootstrapError} (exit 2) when a project-scoped command runs with no
|
|
33
|
+
* discoverable opensip-cli project (scope === 'none').
|
|
34
|
+
*/
|
|
35
|
+
export declare function checkNoProjectAndBailout(project: ProjectContext, cwd: string, cmdName: string, runId: string, extraAgnostic?: ReadonlySet<string>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Phantom-runtime warning. Detects orphaned opensip-cli/.runtime/
|
|
38
|
+
* subtrees between cwd and the discovered project root — fossils from
|
|
39
|
+
* pre-discovery runs that scaffolded under subdirs. Warns to stderr
|
|
40
|
+
* with a safe `rm -rf` hint; never auto-deletes. Suppressed for JSON
|
|
41
|
+
* output (would corrupt the stream's stderr peer in some tools).
|
|
42
|
+
*/
|
|
43
|
+
export declare function warnAboutPhantomRuntimes(project: ProjectContext, jsonOutput: boolean): void;
|
|
44
|
+
//# sourceMappingURL=pre-action-guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-action-guards.d.ts","sourceRoot":"","sources":["../../src/bootstrap/pre-action-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,mBAAmB,CAAC;AA+B3B;;;;;;;;;;GAUG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAmCzF;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,cAAc,EACvB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,aAAa,GAAE,WAAW,CAAC,MAAM,CAAa,GAC7C,IAAI,CAgBN;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAa3F"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pre-action-guards — the pure bailout / warning guards the bootstrap
|
|
3
|
+
* `preAction` hook runs inside its decision window, BEFORE any side effect
|
|
4
|
+
* fires (see `pre-action-hook.ts` for the load-bearing ordering).
|
|
5
|
+
*
|
|
6
|
+
* Extracted from `pre-action-hook.ts` as a cohesive unit: each guard is a
|
|
7
|
+
* `(project, …) => void` that either exits the process with an actionable
|
|
8
|
+
* message (schema-too-old, no-project) or warns to stderr (phantom runtimes),
|
|
9
|
+
* and nothing else. Housing them here keeps the hook module focused on the
|
|
10
|
+
* orchestration sequence and the per-tool `initialize()` lifecycle.
|
|
11
|
+
*/
|
|
12
|
+
import { checkSchemaCompat, detectPhantomRuntimes, logger, readConfigSchemaVersion, } from '@opensip-cli/core';
|
|
13
|
+
import { BootstrapError } from './bootstrap-error.js';
|
|
14
|
+
import { formatCliTooOldMessage, formatNoProjectFoundMessage } from './pre-action-messages.js';
|
|
15
|
+
const MODULE_TAG = 'cli:bootstrap';
|
|
16
|
+
/**
|
|
17
|
+
* Commands that operate WITHOUT requiring a project context. These don't
|
|
18
|
+
* read project files or the datastore; running them from a directory
|
|
19
|
+
* with no opensip-cli project is legitimate.
|
|
20
|
+
*
|
|
21
|
+
* Everything else is project-scoped: when `project.scope === 'none'`,
|
|
22
|
+
* the hook emits the "No OpenSIP CLI project found" error and exits 2.
|
|
23
|
+
*
|
|
24
|
+
* Note: `uninstall --user` is project-agnostic, but `uninstall --project`
|
|
25
|
+
* requires one. The check is per-command name here; uninstall's own
|
|
26
|
+
* mode-specific guarding lives in its action body.
|
|
27
|
+
*
|
|
28
|
+
* The base list covers pure host commands. Tool CommandSpecs that declare
|
|
29
|
+
* `scope: 'none'` are added dynamically at runtime (see pre-action-hook)
|
|
30
|
+
* so the declared `CommandSpec.scope` actually controls behavior (previously
|
|
31
|
+
* this list was the only source of truth, making the field dead for tools).
|
|
32
|
+
*/
|
|
33
|
+
const PROJECT_AGNOSTIC_COMMANDS = new Set([
|
|
34
|
+
'init',
|
|
35
|
+
'configure',
|
|
36
|
+
'completion',
|
|
37
|
+
'uninstall',
|
|
38
|
+
]);
|
|
39
|
+
/**
|
|
40
|
+
* Schema-version bailout. THROWS a {@link BootstrapError} (exit 2) with the
|
|
41
|
+
* "upgrade your CLI" message when the project config declares a schema newer than
|
|
42
|
+
* this CLI knows. Direction-correct: `migrate` would go the other way (old → new);
|
|
43
|
+
* when the CLI itself is behind, the user must upgrade it. The top-level boundary
|
|
44
|
+
* renders it (human stderr / structured `--json`); this guard no longer writes or
|
|
45
|
+
* exits (§4.7).
|
|
46
|
+
*
|
|
47
|
+
* @throws {BootstrapError} (exit 2) when the project config's schema is newer than
|
|
48
|
+
* this CLI supports — the boundary renders the "upgrade your CLI" message.
|
|
49
|
+
*/
|
|
50
|
+
export function checkSchemaVersionAndBailout(project, runId) {
|
|
51
|
+
if (project.scope !== 'project' || project.configPath === undefined)
|
|
52
|
+
return;
|
|
53
|
+
const configVersion = readConfigSchemaVersion(project.configPath);
|
|
54
|
+
const compat = checkSchemaCompat(configVersion);
|
|
55
|
+
if (compat.kind === 'cli-too-old') {
|
|
56
|
+
const msg = formatCliTooOldMessage({
|
|
57
|
+
root: project.projectRoot,
|
|
58
|
+
configVersion: compat.configVersion,
|
|
59
|
+
cliVersion: compat.cliVersion,
|
|
60
|
+
});
|
|
61
|
+
logger.warn({
|
|
62
|
+
evt: 'cli.config.schema.cli-too-old',
|
|
63
|
+
module: MODULE_TAG,
|
|
64
|
+
runId,
|
|
65
|
+
root: project.projectRoot,
|
|
66
|
+
configVersion: compat.configVersion,
|
|
67
|
+
cliVersion: compat.cliVersion,
|
|
68
|
+
});
|
|
69
|
+
throw new BootstrapError({
|
|
70
|
+
message: `This project's opensip-cli.config.yml uses a newer schema (v${compat.configVersion}) than this CLI supports (v${compat.cliVersion}).`,
|
|
71
|
+
humanMessage: msg,
|
|
72
|
+
suggestion: 'Update your CLI: curl -fsSL https://opensip.ai/cli/install.sh | bash',
|
|
73
|
+
exitCode: 2,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (compat.kind === 'older') {
|
|
77
|
+
logger.info({
|
|
78
|
+
evt: 'cli.config.schema.older',
|
|
79
|
+
module: MODULE_TAG,
|
|
80
|
+
runId,
|
|
81
|
+
root: project.projectRoot,
|
|
82
|
+
configVersion: compat.configVersion,
|
|
83
|
+
cliVersion: compat.cliVersion,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* No-project-found bailout. THROWS a {@link BootstrapError} (exit 2) for
|
|
89
|
+
* project-scoped commands when discovery resolved scope === 'none'. The top-level
|
|
90
|
+
* boundary renders it: human mode writes the unchanged multi-line explainer to
|
|
91
|
+
* stderr; `--json` emits a structured `bootstrap.error` outcome (§4.7). The guard
|
|
92
|
+
* no longer branches on json or writes a stream itself.
|
|
93
|
+
*
|
|
94
|
+
* @throws {BootstrapError} (exit 2) when a project-scoped command runs with no
|
|
95
|
+
* discoverable opensip-cli project (scope === 'none').
|
|
96
|
+
*/
|
|
97
|
+
export function checkNoProjectAndBailout(project, cwd, cmdName, runId, extraAgnostic = new Set()) {
|
|
98
|
+
const effective = new Set([...PROJECT_AGNOSTIC_COMMANDS, ...extraAgnostic]);
|
|
99
|
+
if (project.scope !== 'none' || effective.has(cmdName))
|
|
100
|
+
return;
|
|
101
|
+
logger.warn({
|
|
102
|
+
evt: 'cli.project.not-found',
|
|
103
|
+
module: MODULE_TAG,
|
|
104
|
+
runId,
|
|
105
|
+
cwd,
|
|
106
|
+
command: cmdName,
|
|
107
|
+
});
|
|
108
|
+
throw new BootstrapError({
|
|
109
|
+
message: `No opensip-cli.config.yml found. Searched from ${cwd} upward.`,
|
|
110
|
+
humanMessage: formatNoProjectFoundMessage(cwd),
|
|
111
|
+
suggestion: 'Run opensip init to get started.',
|
|
112
|
+
exitCode: 2,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Phantom-runtime warning. Detects orphaned opensip-cli/.runtime/
|
|
117
|
+
* subtrees between cwd and the discovered project root — fossils from
|
|
118
|
+
* pre-discovery runs that scaffolded under subdirs. Warns to stderr
|
|
119
|
+
* with a safe `rm -rf` hint; never auto-deletes. Suppressed for JSON
|
|
120
|
+
* output (would corrupt the stream's stderr peer in some tools).
|
|
121
|
+
*/
|
|
122
|
+
export function warnAboutPhantomRuntimes(project, jsonOutput) {
|
|
123
|
+
if (jsonOutput)
|
|
124
|
+
return;
|
|
125
|
+
if (project.scope !== 'project' || project.walkedUp === 0)
|
|
126
|
+
return;
|
|
127
|
+
const phantoms = detectPhantomRuntimes(project.cwd, project.projectRoot);
|
|
128
|
+
for (const phantom of phantoms) {
|
|
129
|
+
process.stderr.write(`ℹ Detected an orphaned opensip-cli/ at:\n` +
|
|
130
|
+
` ${phantom}\n` +
|
|
131
|
+
` Left over from running opensip from this subdirectory\n` +
|
|
132
|
+
` before project-root discovery was added. Safe to delete with:\n` +
|
|
133
|
+
` rm -rf ${phantom}\n\n`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=pre-action-guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-action-guards.js","sourceRoot":"","sources":["../../src/bootstrap/pre-action-guards.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pre-action-hook — Commander `preAction` body.
|
|
3
|
+
*
|
|
4
|
+
* Runs before every subcommand's action. Centralises run-id generation,
|
|
5
|
+
* config-merge, project-context resolution, schema-version bailout, and
|
|
6
|
+
* (only when the run will proceed) log file initialisation. Datastore is
|
|
7
|
+
* NOT opened here — that's a lazy getter on ToolCliContext (Task 1.3).
|
|
8
|
+
*
|
|
9
|
+
* Ordering is load-bearing: side effects only fire AFTER all bailout
|
|
10
|
+
* decisions. Sequence:
|
|
11
|
+
*
|
|
12
|
+
* 1. generate runId
|
|
13
|
+
* 2. read opts; resolve project context (pure; may throw on strict --config)
|
|
14
|
+
* 3. expose context on opts.projectContext (collision-free name)
|
|
15
|
+
* 4. bailout window — schema check (Phase 6.3), phantom warn (Phase 7)
|
|
16
|
+
* 5. side-effect setup — configureLogger({ logDir }) + setProjectContextForRun
|
|
17
|
+
* gated on project.scope === 'project' && existsSync(projectRoot)
|
|
18
|
+
* 6. Project: header (Phase 2.2)
|
|
19
|
+
* 7. cli.start log line
|
|
20
|
+
* 8. lazy Tool.initialize() — run the owning tool's optional one-time
|
|
21
|
+
* init exactly once per process, after the scope is entered and just
|
|
22
|
+
* before the action body (P1a). CLI-only commands have no owner and
|
|
23
|
+
* skip it; a failing init is fatal.
|
|
24
|
+
*
|
|
25
|
+
* Strict --config: when `--config <path>` doesn't resolve, the
|
|
26
|
+
* underlying ValidationError surfaces with exit 2 — no silent walk-up.
|
|
27
|
+
*/
|
|
28
|
+
import { type LanguageRegistry, type ToolPluginManifest, type ToolProvenance, type ToolRegistry } from '@opensip-cli/core';
|
|
29
|
+
import type { Command } from 'commander';
|
|
30
|
+
export { resolveOwningTool } from './owning-tool-init.js';
|
|
31
|
+
/**
|
|
32
|
+
* The `scope.configDocument` slot value (ADR-0023 one-reader): the validated
|
|
33
|
+
* document rides the scope so tools project their shapes from it instead of
|
|
34
|
+
* re-reading the file — but ONLY when a real config file was read. A
|
|
35
|
+
* config-less run stays document-less so tools that hard-error on a missing
|
|
36
|
+
* config (fitness) stay loud instead of silently validating `{}`.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* The per-invocation bootstrap result the hook needs to BUILD the scope —
|
|
40
|
+
* the populated registries plus the admitted-tool manifests/provenance. These
|
|
41
|
+
* are created in `main()` BEFORE the scope can be constructed (the registries
|
|
42
|
+
* are inputs to `RunScope`; you can't read them off a scope that doesn't exist
|
|
43
|
+
* yet), so the composition root captures them in this closure and hands them to
|
|
44
|
+
* `installPreActionHook`. After the hook calls `enterScope`, every per-run read
|
|
45
|
+
* (project, datastore, manifests, provenance, …) goes through `currentScope()`
|
|
46
|
+
* — there is NO module-global handoff bag (the former `currentRuntimeContext`).
|
|
47
|
+
*/
|
|
48
|
+
export interface PreActionRuntime {
|
|
49
|
+
readonly languages: LanguageRegistry;
|
|
50
|
+
readonly tools: ToolRegistry;
|
|
51
|
+
readonly manifests: readonly ToolPluginManifest[];
|
|
52
|
+
readonly provenance: readonly ToolProvenance[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Mount the bootstrap `preAction` hook on the supplied program.
|
|
56
|
+
*
|
|
57
|
+
* @param program The root Commander program.
|
|
58
|
+
* @param version The CLI version (from `readPackageVersion` at the entry
|
|
59
|
+
* point). Threaded in rather than re-read here so the `mini` banner shows
|
|
60
|
+
* the SAME version `--version` reports — and so the kernel-adjacent hook
|
|
61
|
+
* doesn't resolve cli-ui's or its own package version by mistake.
|
|
62
|
+
* @param runtime The bootstrap result (registries + admitted manifests/
|
|
63
|
+
* provenance). Captured in the hook closure instead of read from a module
|
|
64
|
+
* global — the composition root installs the hook AFTER `bootstrapCli`
|
|
65
|
+
* populates the registries (see {@link PreActionRuntime}).
|
|
66
|
+
*/
|
|
67
|
+
export declare function installPreActionHook(program: Command, version: string, runtime: PreActionRuntime): void;
|
|
68
|
+
//# sourceMappingURL=pre-action-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-action-hook.d.ts","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,EASL,KAAK,gBAAgB,EAErB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAiB3B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;;;GAMG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAClD,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;CAChD;AAED;;;;;;;;;;;;GAYG;AAUH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,IAAI,CAqPN"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// @fitness-ignore-file detached-promises -- the preAction hook is a composition root: its body invokes synchronous bootstrap helpers (mergeConfigDefaults, configureLogger, the checkSchemaVersion/checkNoProject/warnAboutPhantom bailout guards, enterScope) that the name-based heuristic mistakes for promise-returning calls. The one genuine async call (maybeInitializeOwningTool) is awaited. Matches the same suppression on index.ts and bootstrap/index.ts.
|
|
2
|
+
/**
|
|
3
|
+
* pre-action-hook — Commander `preAction` body.
|
|
4
|
+
*
|
|
5
|
+
* Runs before every subcommand's action. Centralises run-id generation,
|
|
6
|
+
* config-merge, project-context resolution, schema-version bailout, and
|
|
7
|
+
* (only when the run will proceed) log file initialisation. Datastore is
|
|
8
|
+
* NOT opened here — that's a lazy getter on ToolCliContext (Task 1.3).
|
|
9
|
+
*
|
|
10
|
+
* Ordering is load-bearing: side effects only fire AFTER all bailout
|
|
11
|
+
* decisions. Sequence:
|
|
12
|
+
*
|
|
13
|
+
* 1. generate runId
|
|
14
|
+
* 2. read opts; resolve project context (pure; may throw on strict --config)
|
|
15
|
+
* 3. expose context on opts.projectContext (collision-free name)
|
|
16
|
+
* 4. bailout window — schema check (Phase 6.3), phantom warn (Phase 7)
|
|
17
|
+
* 5. side-effect setup — configureLogger({ logDir }) + setProjectContextForRun
|
|
18
|
+
* gated on project.scope === 'project' && existsSync(projectRoot)
|
|
19
|
+
* 6. Project: header (Phase 2.2)
|
|
20
|
+
* 7. cli.start log line
|
|
21
|
+
* 8. lazy Tool.initialize() — run the owning tool's optional one-time
|
|
22
|
+
* init exactly once per process, after the scope is entered and just
|
|
23
|
+
* before the action body (P1a). CLI-only commands have no owner and
|
|
24
|
+
* skip it; a failing init is fatal.
|
|
25
|
+
*
|
|
26
|
+
* Strict --config: when `--config <path>` doesn't resolve, the
|
|
27
|
+
* underlying ValidationError surfaces with exit 2 — no silent walk-up.
|
|
28
|
+
*/
|
|
29
|
+
import { existsSync } from 'node:fs';
|
|
30
|
+
import { configureLogger, currentScope, enterScope, generatePrefixedId, logger, resolveProjectContext, resolveProjectPaths, SystemError, } from '@opensip-cli/core';
|
|
31
|
+
import { getMeter } from '@opensip-cli/core';
|
|
32
|
+
import { startProfiling } from '../telemetry/profiling.js';
|
|
33
|
+
import { checkForUpdate, formatUpdateNag } from '../update-notifier.js';
|
|
34
|
+
import { BootstrapError } from './bootstrap-error.js';
|
|
35
|
+
import { buildPerRunScope } from './build-per-run-scope.js';
|
|
36
|
+
import { loadCliDefaults, mergeConfigDefaults } from './cli-defaults.js';
|
|
37
|
+
import { loadOwningToolCapabilities } from './load-tool-capabilities.js';
|
|
38
|
+
import { maybeInitializeOwningTool, resolveOwningTool } from './owning-tool-init.js';
|
|
39
|
+
import { checkNoProjectAndBailout, checkSchemaVersionAndBailout, warnAboutPhantomRuntimes, } from './pre-action-guards.js';
|
|
40
|
+
/** npm package whose version the update check compares against. */
|
|
41
|
+
const CLI_PACKAGE_NAME = 'opensip-cli';
|
|
42
|
+
const MODULE_TAG = 'cli:bootstrap';
|
|
43
|
+
// Owning-tool resolution + lazy `Tool.initialize()` live in `owning-tool-init.ts`
|
|
44
|
+
// (also imported below for local use). `resolveOwningTool` is re-exported so
|
|
45
|
+
// existing importers (e.g. the lifecycle test) keep their stable
|
|
46
|
+
// `pre-action-hook.js` entry point.
|
|
47
|
+
export { resolveOwningTool } from './owning-tool-init.js';
|
|
48
|
+
/**
|
|
49
|
+
* Mount the bootstrap `preAction` hook on the supplied program.
|
|
50
|
+
*
|
|
51
|
+
* @param program The root Commander program.
|
|
52
|
+
* @param version The CLI version (from `readPackageVersion` at the entry
|
|
53
|
+
* point). Threaded in rather than re-read here so the `mini` banner shows
|
|
54
|
+
* the SAME version `--version` reports — and so the kernel-adjacent hook
|
|
55
|
+
* doesn't resolve cli-ui's or its own package version by mistake.
|
|
56
|
+
* @param runtime The bootstrap result (registries + admitted manifests/
|
|
57
|
+
* provenance). Captured in the hook closure instead of read from a module
|
|
58
|
+
* global — the composition root installs the hook AFTER `bootstrapCli`
|
|
59
|
+
* populates the registries (see {@link PreActionRuntime}).
|
|
60
|
+
*/
|
|
61
|
+
// The body (including the preAction hook arrow it registers) sequences the full
|
|
62
|
+
// per-invocation bootstrap: runId, defaults merge, project resolve + bailouts,
|
|
63
|
+
// scope construction/enter, metrics, profiling start, lazy tool init, capability
|
|
64
|
+
// drive. It has many explicit early-exit paths by design (the documented contract
|
|
65
|
+
// for "only side effects after all bailouts"). Cognitive complexity exceeds 15
|
|
66
|
+
// because it is the single source of truth for ordering; splitting would obscure
|
|
67
|
+
// the load-bearing sequence and duplicate the guard/enter wiring. Acceptable for
|
|
68
|
+
// this composition root (see similar disables on other bootstrap entry points).
|
|
69
|
+
/* eslint-disable sonarjs/cognitive-complexity -- single source of truth for scope construction/enter ordering; splitting would obscure the load-bearing sequence (rationale above) */
|
|
70
|
+
export function installPreActionHook(program, version, runtime) {
|
|
71
|
+
program.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
72
|
+
const runId = generatePrefixedId('run');
|
|
73
|
+
const opts = actionCommand.opts();
|
|
74
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
75
|
+
const cwdExplicit = actionCommand.getOptionValueSource('cwd') === 'cli';
|
|
76
|
+
// Keep the loaded defaults around: `mergeConfigDefaults` only copies the
|
|
77
|
+
// flag-shaped fields onto opts, but `ui.banner` has no flag — we read it
|
|
78
|
+
// straight off the config object below to build the UiContext.
|
|
79
|
+
const cliDefaults = loadCliDefaults(cwd, opts.config);
|
|
80
|
+
mergeConfigDefaults(opts, cliDefaults);
|
|
81
|
+
// Single bootstrap-time configuration of the process-wide logger
|
|
82
|
+
// singleton. Replaces the four prior free mutators (`setSilent`,
|
|
83
|
+
// `setDebugMode`, `setRunId`, `initLogFile`). `logDir` is wired in
|
|
84
|
+
// below once the project context is resolved — at that point the
|
|
85
|
+
// logsDir is known and we apply a second `configureLogger` to fill
|
|
86
|
+
// it in. The two-call sequence is intentional: silencing stderr
|
|
87
|
+
// before the project-resolve step is what makes Ink renders clean
|
|
88
|
+
// even when the project is missing.
|
|
89
|
+
configureLogger({
|
|
90
|
+
silent: true,
|
|
91
|
+
debugMode: Boolean(opts.debug),
|
|
92
|
+
runId,
|
|
93
|
+
});
|
|
94
|
+
// 2. Resolve the project context — pure, no side effects.
|
|
95
|
+
// Strict --config: throws ValidationError when explicit path misses.
|
|
96
|
+
let project;
|
|
97
|
+
try {
|
|
98
|
+
project = resolveProjectContext({
|
|
99
|
+
cwd,
|
|
100
|
+
cwdExplicit,
|
|
101
|
+
explicitConfigPath: opts.config,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
// §4.7: a config-resolve failure (e.g. strict --config miss) becomes a typed
|
|
106
|
+
// BootstrapError the top-level boundary renders — human stderr / structured
|
|
107
|
+
// --json — instead of an inline stderr write + process.exit.
|
|
108
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
109
|
+
throw new BootstrapError({
|
|
110
|
+
message: msg,
|
|
111
|
+
humanMessage: `✗ ${msg}`,
|
|
112
|
+
suggestion: 'Check opensip-cli.config.yml (or your --config path).',
|
|
113
|
+
exitCode: 2,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// 3. Stash the context on opts under the COLLISION-FREE name.
|
|
117
|
+
// `opts.project` is reserved for Commander's --project [path] flag
|
|
118
|
+
// in uninstall.ts; we never use that name here.
|
|
119
|
+
opts.projectContext = project;
|
|
120
|
+
// Stash the resolved "was --cwd typed on the CLI?" signal alongside it,
|
|
121
|
+
// so the `init` command-spec handler (launch Phase 6) reads ONE
|
|
122
|
+
// source instead of recomputing `getOptionValueSource('cwd')` on its own
|
|
123
|
+
// Commander command. `actionCommand` IS the init command here, so this is
|
|
124
|
+
// byte-identical to the former register-init computation.
|
|
125
|
+
opts.cwdExplicit = cwdExplicit;
|
|
126
|
+
// 4. Bailout window — each may THROW a BootstrapError (rendered by the
|
|
127
|
+
// top-level boundary) before any side effects. Phantom warn is non-fatal;
|
|
128
|
+
// warns then continues.
|
|
129
|
+
checkSchemaVersionAndBailout(project, runId);
|
|
130
|
+
// Build the effective set of project-agnostic command names from the base list
|
|
131
|
+
// PLUS any tool CommandSpecs that declare scope: 'none'. This makes the
|
|
132
|
+
// declared `CommandSpec.scope` drive enforcement (previously the hardcoded
|
|
133
|
+
// name list made the field dead for tools and third-party commands).
|
|
134
|
+
const extraAgnostic = new Set();
|
|
135
|
+
for (const tool of runtime.tools.list()) {
|
|
136
|
+
for (const c of tool.commands || []) {
|
|
137
|
+
if (c.scope === 'none') {
|
|
138
|
+
extraAgnostic.add(c.name);
|
|
139
|
+
(c.aliases ?? []).forEach((a) => extraAgnostic.add(a));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
checkNoProjectAndBailout(project, cwd, actionCommand.name(), runId, extraAgnostic);
|
|
144
|
+
warnAboutPhantomRuntimes(project, opts.json === true);
|
|
145
|
+
// 5. Side-effect setup, gated on a real project being present.
|
|
146
|
+
if (project.scope === 'project' && existsSync(project.projectRoot)) {
|
|
147
|
+
const projectPaths = resolveProjectPaths(project.projectRoot);
|
|
148
|
+
// Second configureLogger call — fills in the project-scoped logDir
|
|
149
|
+
// now that the project context is resolved. Leaves silent/debugMode/runId
|
|
150
|
+
// untouched (configureLogger only writes fields present in the bag).
|
|
151
|
+
configureLogger({ logDir: projectPaths.logsDir });
|
|
152
|
+
}
|
|
153
|
+
// Build the per-run RunScope and enter it via AsyncLocalStorage so
|
|
154
|
+
// library functions deep in the call tree (currentScope() readers)
|
|
155
|
+
// see the bound logger/registries/project + a lazy datastore thunk.
|
|
156
|
+
// enterWith propagates forward through the same async chain, so the
|
|
157
|
+
// action body invoked after this hook sees the same scope without
|
|
158
|
+
// needing a callback wrapper — which Commander does not expose.
|
|
159
|
+
// (Phase 5 deferred Task 5.2 / T1 Item D close-out.)
|
|
160
|
+
// Resolve presentation + update state once, before the scope is built.
|
|
161
|
+
// bannerSize: explicit `cli.ui.banner`, else the product default `mini`.
|
|
162
|
+
// update: the cached newer-version string (best-effort; undefined when
|
|
163
|
+
// up-to-date / opted-out / non-TTY). The `mini` banner shows it inline;
|
|
164
|
+
// other sizes — and the banner-less `--json` path — fall back to the
|
|
165
|
+
// stderr nag so the signal is never silently lost.
|
|
166
|
+
const bannerSize = cliDefaults.ui?.banner ?? 'mini';
|
|
167
|
+
const update = checkForUpdate({ name: CLI_PACKAGE_NAME, version });
|
|
168
|
+
if (update && (bannerSize !== 'mini' || opts.json === true)) {
|
|
169
|
+
process.stderr.write(formatUpdateNag(version, update));
|
|
170
|
+
}
|
|
171
|
+
// ADR-0008: select the cloud signal sink for this run. Sync + cheap —
|
|
172
|
+
// keyless / `cloud.sync:false` / `--no-cloud` / non-https → no-op with no
|
|
173
|
+
// IO; the entitlement check is deferred to first emit so non-signal
|
|
174
|
+
// commands pay nothing. `opts.cloud === false` comes from `--no-cloud`.
|
|
175
|
+
//
|
|
176
|
+
// `cloud` layers the user-level opt-out (~/.opensip-cli/config.yml#cloud)
|
|
177
|
+
// over the project's `cli.cloud:` block (audit P0-2): a user `sync: false`
|
|
178
|
+
// disables sync for every project on this machine.
|
|
179
|
+
const { languages, tools, manifests, provenance } = runtime;
|
|
180
|
+
// Extracted to thin the composition root (GA architectural blocker #2).
|
|
181
|
+
// All scope construction + wiring now lives in a dedicated small builder
|
|
182
|
+
// with explicit inputs. The hook remains the high-level sequencer. The
|
|
183
|
+
// registries + admitted-tool manifests/provenance come from the closure
|
|
184
|
+
// the composition root captured (no module-global handoff bag); the
|
|
185
|
+
// builder stamps manifests/provenance onto the scope for host commands.
|
|
186
|
+
const scope = buildPerRunScope({
|
|
187
|
+
project,
|
|
188
|
+
runId,
|
|
189
|
+
cwd,
|
|
190
|
+
cliDefaults,
|
|
191
|
+
registries: { languages, tools },
|
|
192
|
+
manifests,
|
|
193
|
+
provenance,
|
|
194
|
+
apiKey: opts.apiKey,
|
|
195
|
+
// @fitness-ignore-next-line null-safety -- Commander's optsWithGlobals() always returns an OptionValues object (never null/undefined); the heuristic misreads the method-call-then-property access. `.cloud` is an absent-or-boolean flag, compared with `=== false`.
|
|
196
|
+
noCloud: actionCommand.optsWithGlobals().cloud === false,
|
|
197
|
+
logger,
|
|
198
|
+
ui: { version, update },
|
|
199
|
+
});
|
|
200
|
+
enterScope(scope);
|
|
201
|
+
// Phase 3 hygiene: scope entry via ALS (enterScope) is now the single source of truth
|
|
202
|
+
// for per-run state. No holder mirror or mark dance. All subsequent readers (including
|
|
203
|
+
// host command bodies) must see a valid currentScope().
|
|
204
|
+
if (!currentScope()) {
|
|
205
|
+
throw new SystemError('Scope was not entered before command dispatch', {
|
|
206
|
+
code: 'SYSTEM.SCOPE.NOT_ENTERED',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
// Lifecycle diagnostics (§5.10): record key construction facts on the per-run bus.
|
|
210
|
+
// These (plus the per-domain events emitted from loadCapabilityDomain and the
|
|
211
|
+
// wiring events from buildPerRunScope) ride on every CommandOutcome so --json
|
|
212
|
+
// consumers see the full uniform lifecycle (tools loaded, subscopes contributed,
|
|
213
|
+
// capability domains wired + driven, config validated, etc.). This directly
|
|
214
|
+
// improves observability of the blast-radius bootstrap paths (architecture review).
|
|
215
|
+
scope.diagnostics.event('load', 'debug', `${tools.list().length} tool(s) loaded`);
|
|
216
|
+
scope.diagnostics.counter('tools.loaded', tools.list().length);
|
|
217
|
+
// Phase 2 metrics (low cardinality)
|
|
218
|
+
getMeter('opensip-cli').createCounter('opensip_cli.commands.started').add(1, {
|
|
219
|
+
command: actionCommand.name(),
|
|
220
|
+
});
|
|
221
|
+
scope.diagnostics.event('validate', 'debug', `project config resolved (scope: ${project.scope})`);
|
|
222
|
+
// The `ℹ Project:` location line is rendered once, under the banner,
|
|
223
|
+
// by cli-ui's ProjectHeader — mounted by the App shell (static
|
|
224
|
+
// commands, via render.ts reading currentScope().project) and by each
|
|
225
|
+
// live view (fit/graph). No imperative pre-action print.
|
|
226
|
+
// Structured start log.
|
|
227
|
+
logger.info({
|
|
228
|
+
evt: 'cli.run.start',
|
|
229
|
+
module: MODULE_TAG,
|
|
230
|
+
runId,
|
|
231
|
+
command: actionCommand.name(),
|
|
232
|
+
cwd,
|
|
233
|
+
projectRoot: project.projectRoot,
|
|
234
|
+
scope: project.scope,
|
|
235
|
+
});
|
|
236
|
+
if (project.walkedUp > 0) {
|
|
237
|
+
logger.info({
|
|
238
|
+
evt: 'cli.project.discovered',
|
|
239
|
+
module: MODULE_TAG,
|
|
240
|
+
runId,
|
|
241
|
+
cwd,
|
|
242
|
+
projectRoot: project.projectRoot,
|
|
243
|
+
walkedUp: project.walkedUp,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// Optional profiling (Phase 3, severable). Start after scope (runId available).
|
|
247
|
+
// Respects the dual-gate (OPENSIP_PROFILING + OTEL) or OTEL-only fallback.
|
|
248
|
+
startProfiling(scope, actionCommand.name());
|
|
249
|
+
// 8. Lazy, memoized Tool.initialize() — runs the owning tool's
|
|
250
|
+
// optional one-time init here, AFTER enterScope (so eager setup that
|
|
251
|
+
// registers packs / reads currentScope() sees the bound scope) and
|
|
252
|
+
// immediately before Commander invokes the action body. See the
|
|
253
|
+
// helper for the once-per-process + fail-fast semantics.
|
|
254
|
+
await maybeInitializeOwningTool(tools, actionCommand.name(), runId);
|
|
255
|
+
// 9. §5.3/§4.5: drive the generic capability loader for the invoked tool's
|
|
256
|
+
// declared domains (e.g. graph-adapter). Lazy per command — only the
|
|
257
|
+
// owning tool's domains load, routed through the host's capability
|
|
258
|
+
// registry to each owner's registrar. Replaces the host-coupled,
|
|
259
|
+
// eager register-graph-adapters.ts.
|
|
260
|
+
const driven = await loadOwningToolCapabilities({
|
|
261
|
+
owningTool: resolveOwningTool(tools, actionCommand.name()),
|
|
262
|
+
projectDir: project.projectRoot,
|
|
263
|
+
configPath: project.scope === 'project' ? project.configPath : undefined,
|
|
264
|
+
});
|
|
265
|
+
if (driven > 0) {
|
|
266
|
+
scope.diagnostics.event('load', 'debug', `drove ${String(driven)} owning-tool capability domain(s) (see per-domain 'capability ... loaded' events for contribution counts + errors)`);
|
|
267
|
+
scope.diagnostics.counter('capabilities.driven', driven);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
// Resilience: best-effort release of per-run resources (parseCache, recipe config slot,
|
|
271
|
+
// contributed sub-scopes, diagnostics bus) after the action body completes for every
|
|
272
|
+
// command. Complements the narrow dispose() impl and the current lack of finally in
|
|
273
|
+
// many paths. postAction fires for normal completion; error paths are covered by
|
|
274
|
+
// handleParseError + handleFatalBootstrapError (which may also dispose in future passes).
|
|
275
|
+
// Idempotent: dispose is cheap and safe to call more than once.
|
|
276
|
+
program.hook('postAction', () => {
|
|
277
|
+
try {
|
|
278
|
+
const s = currentScope();
|
|
279
|
+
if (s && typeof s.dispose === 'function') {
|
|
280
|
+
s.dispose();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// @swallow-ok dispose errors on shutdown; the run has already produced its outcome.
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/* eslint-enable sonarjs/cognitive-complexity */
|
|
289
|
+
//# sourceMappingURL=pre-action-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-action-hook.js","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"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"}
|