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
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenSIP CLI — composition root (sequencer, not a god file).
|
|
4
|
+
*
|
|
5
|
+
* The canonical ordered description of the full tool + host lifecycle lives in
|
|
6
|
+
* `bootstrap/tool-lifecycle.ts` (the 10 named steps, two phases: STARTUP in
|
|
7
|
+
* bootstrapCli + mountToolCommands, PER-RUN in the preAction hook + builders).
|
|
8
|
+
* This file wires the major seams (fresh registries per invocation, bootstrap,
|
|
9
|
+
* pre-action hook install, ToolCliContext construction, command mounting,
|
|
10
|
+
* host command registration, telemetry, top-level error paths) and then
|
|
11
|
+
* dispatches. Individual steps are factored into `./bootstrap/*` (admission,
|
|
12
|
+
* scope building, capability wiring, delivery) and `./commands/*`.
|
|
13
|
+
*
|
|
14
|
+
* Adding a new tool requires zero changes here — tools declare `commandSpecs`
|
|
15
|
+
* (and optional hooks) and are discovered/admitted/mounted uniformly.
|
|
16
|
+
*
|
|
17
|
+
* See also: bootstrap/tool-lifecycle.ts (TOOL_LIFECYCLE_STEPS + JSDoc),
|
|
18
|
+
* pre-action-hook.ts, build-per-run-scope.ts, register-tools.ts.
|
|
19
|
+
*/
|
|
20
|
+
export * from './api.js';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAGA;;;;;;;;;;;;;;;;;GAiBG;AA4BH,cAAc,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @fitness-ignore-file detached-promises -- composition root invokes synchronous bootstrap helpers (mountAllToolCommands, registerCliCommands, printWelcome) that the heuristic mistakes for promise-returning calls
|
|
3
|
+
/**
|
|
4
|
+
* OpenSIP CLI — composition root (sequencer, not a god file).
|
|
5
|
+
*
|
|
6
|
+
* The canonical ordered description of the full tool + host lifecycle lives in
|
|
7
|
+
* `bootstrap/tool-lifecycle.ts` (the 10 named steps, two phases: STARTUP in
|
|
8
|
+
* bootstrapCli + mountToolCommands, PER-RUN in the preAction hook + builders).
|
|
9
|
+
* This file wires the major seams (fresh registries per invocation, bootstrap,
|
|
10
|
+
* pre-action hook install, ToolCliContext construction, command mounting,
|
|
11
|
+
* host command registration, telemetry, top-level error paths) and then
|
|
12
|
+
* dispatches. Individual steps are factored into `./bootstrap/*` (admission,
|
|
13
|
+
* scope building, capability wiring, delivery) and `./commands/*`.
|
|
14
|
+
*
|
|
15
|
+
* Adding a new tool requires zero changes here — tools declare `commandSpecs`
|
|
16
|
+
* (and optional hooks) and are discovered/admitted/mounted uniformly.
|
|
17
|
+
*
|
|
18
|
+
* See also: bootstrap/tool-lifecycle.ts (TOOL_LIFECYCLE_STEPS + JSDoc),
|
|
19
|
+
* pre-action-hook.ts, build-per-run-scope.ts, register-tools.ts.
|
|
20
|
+
*/
|
|
21
|
+
import { dirname } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
import { LanguageRegistry, ToolRegistry, logger, readPackageVersion, getMeter, } from '@opensip-cli/core';
|
|
24
|
+
import { Command } from 'commander';
|
|
25
|
+
import { bootstrapCli, installPreActionHook, maybeOpenReport, mountToolCommands, renderResult, buildCommandRegistrationInput, } from './bootstrap/index.js';
|
|
26
|
+
import { buildToolCliContext, createLiveViewRegistry, getOrOpenDatastore } from './cli-context.js';
|
|
27
|
+
import { registerCliCommands } from './commands/index.js';
|
|
28
|
+
import { handleFatalBootstrapError, handleParseError } from './error-handler.js';
|
|
29
|
+
import { runWithTelemetryContext, shutdownTelemetry } from './telemetry/sdk-init.js';
|
|
30
|
+
import { printWelcome } from './welcome.js';
|
|
31
|
+
export * from './api.js';
|
|
32
|
+
const cliVersion = readPackageVersion(import.meta.url);
|
|
33
|
+
const program = new Command('opensip')
|
|
34
|
+
.description('Codebase analysis toolkit — pluggable tools for fitness, simulation, and more')
|
|
35
|
+
// ADR-0008: per-run opt-out of OpenSIP Cloud signal sync. `--no-cloud` sets
|
|
36
|
+
// `cloud` to false; the pre-action hook reads it via optsWithGlobals().
|
|
37
|
+
.option('--no-cloud', 'Disable OpenSIP Cloud signal sync for this run')
|
|
38
|
+
.version(cliVersion)
|
|
39
|
+
// Route Commander's own parse failures through `parseAsync().catch` →
|
|
40
|
+
// `handleParseError` instead of letting Commander call `process.exit(N)`
|
|
41
|
+
// directly. This restores the project's typed-error → exit-code contract for
|
|
42
|
+
// declarative `choices`/argument validation: a bad `--resolution`/option
|
|
43
|
+
// value is a usage error that must exit `CONFIGURATION_ERROR` (2) — the same
|
|
44
|
+
// code the pre-command-plane in-handler `ValidationError` produced — not
|
|
45
|
+
// Commander's default `1`. `handleParseError` preserves Commander's own
|
|
46
|
+
// exit code for every OTHER Commander condition (unknown command/option →
|
|
47
|
+
// 1, --help/--version → 0), so only the invalid-argument case is re-mapped.
|
|
48
|
+
// Commander still writes its own error line to stderr before throwing, so the
|
|
49
|
+
// handler renders nothing extra for a CommanderError (no duplicate output).
|
|
50
|
+
.exitOverride();
|
|
51
|
+
async function main() {
|
|
52
|
+
// Fresh registries per CLI invocation. Tools read these via
|
|
53
|
+
// `cli.scope.languages` / `cli.scope.tools`; bootstrap populates them here.
|
|
54
|
+
const langRegistry = new LanguageRegistry();
|
|
55
|
+
const toolRegistry = new ToolRegistry();
|
|
56
|
+
// Persistence: datastore is opened LAZILY in cli-context.ts on
|
|
57
|
+
// first access via getOrOpenDatastore. bootstrapCli just registers
|
|
58
|
+
// tools and adapters; no SQLite file is created here.
|
|
59
|
+
const { provenance, manifests } = await bootstrapCli({
|
|
60
|
+
langRegistry,
|
|
61
|
+
toolRegistry,
|
|
62
|
+
projectDir: dirname(dirname(fileURLToPath(import.meta.url))),
|
|
63
|
+
cwd: process.cwd(),
|
|
64
|
+
cliEntryUrl: import.meta.url,
|
|
65
|
+
});
|
|
66
|
+
// Install the pre-action hook AFTER bootstrap so the populated registries +
|
|
67
|
+
// admitted-tool manifests/provenance are captured directly in the hook
|
|
68
|
+
// closure — no module-global handoff bag. The hook builds + enters the
|
|
69
|
+
// per-run RunScope (stamping manifests/provenance onto it); from there every
|
|
70
|
+
// per-run read goes through `currentScope()`.
|
|
71
|
+
installPreActionHook(program, cliVersion, {
|
|
72
|
+
languages: langRegistry,
|
|
73
|
+
tools: toolRegistry,
|
|
74
|
+
manifests,
|
|
75
|
+
provenance,
|
|
76
|
+
});
|
|
77
|
+
const { ctx } = buildToolCliContext({
|
|
78
|
+
render: renderResult,
|
|
79
|
+
liveViews: createLiveViewRegistry(logger),
|
|
80
|
+
maybeOpenReport,
|
|
81
|
+
logger,
|
|
82
|
+
});
|
|
83
|
+
// Step 8 of the tool lifecycle (§5.4): mount each registered tool's commands
|
|
84
|
+
// through the named sequencer seam. The host owns `program` and passes it in
|
|
85
|
+
// (launch — the tool context no longer carries a raw-Commander handle, §8); the
|
|
86
|
+
// one command surface is each tool's declarative commandSpecs.
|
|
87
|
+
mountToolCommands(toolRegistry, program, ctx);
|
|
88
|
+
// Extracted into a thin dedicated builder (roadmap item 2) to keep the
|
|
89
|
+
// top-level composition root focused on sequencing. The builder returns the
|
|
90
|
+
// exact shape consumed by `registerCliCommands`.
|
|
91
|
+
const registrationInput = buildCommandRegistrationInput(toolRegistry);
|
|
92
|
+
registerCliCommands(program, {
|
|
93
|
+
setExitCode: ctx.setExitCode,
|
|
94
|
+
render: renderResult,
|
|
95
|
+
emitJson: ctx.emitJson,
|
|
96
|
+
emitRaw: ctx.emitRaw,
|
|
97
|
+
emitError: ctx.emitError,
|
|
98
|
+
datastore: () => getOrOpenDatastore(logger),
|
|
99
|
+
...registrationInput,
|
|
100
|
+
});
|
|
101
|
+
// Bare `opensip` → welcome screen. The update check is owned by the
|
|
102
|
+
// pre-action hook (which only runs for actual subcommands), so it naturally
|
|
103
|
+
// skips zero-arg runs without a guard here.
|
|
104
|
+
// Return (not process.exit) so the top-level `finally` still runs the
|
|
105
|
+
// telemetry shutdown flush — consistent with this file's exitCode-over-
|
|
106
|
+
// exit() principle below. Exit code defaults to 0.
|
|
107
|
+
if (process.argv.length <= 2) {
|
|
108
|
+
printWelcome({ version: program.version() ?? 'dev' });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Dispatch inside the telemetry parent context so spans emitted during the
|
|
112
|
+
// run (e.g. graph's per-stage spans) nest under the consumer's TRACEPARENT
|
|
113
|
+
// when one was supplied. A plain pass-through when telemetry is disabled or
|
|
114
|
+
// no parent context was extracted, so standalone runs pay nothing.
|
|
115
|
+
// `--json` is read from argv here because bootstrap/parse errors fire OUTSIDE a
|
|
116
|
+
// handler (no parsed opts). It selects the structured `CommandOutcome` error
|
|
117
|
+
// path (§5.5) over human Ink rendering.
|
|
118
|
+
const jsonRequested = process.argv.includes('--json');
|
|
119
|
+
const commandStart = Date.now();
|
|
120
|
+
await runWithTelemetryContext(() => program.parseAsync().catch((error) => handleParseError(error, {
|
|
121
|
+
setExitCode: ctx.setExitCode,
|
|
122
|
+
render: renderResult,
|
|
123
|
+
jsonRequested,
|
|
124
|
+
})));
|
|
125
|
+
// Phase 2: command duration histogram (low cardinality labels)
|
|
126
|
+
const durationMs = Date.now() - commandStart;
|
|
127
|
+
getMeter('opensip-cli')
|
|
128
|
+
.createHistogram('opensip_cli.command.duration_ms')
|
|
129
|
+
.record(durationMs, {
|
|
130
|
+
command: process.argv[2] || 'welcome', // rough; real commands go through pre-action
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Top-level fatal handler. Errors that escape `main` predate Commander's
|
|
134
|
+
// parse loop (bootstrap, registry registration, fs I/O during preflight)
|
|
135
|
+
// and so don't reach the per-command catch in `parseAsync().catch(...)`.
|
|
136
|
+
// Route them through the same error-handler seam so the exit code flows
|
|
137
|
+
// through `process.exitCode` (not `process.exit(N)` — the latter skips
|
|
138
|
+
// the pending stderr flush) and a `cli.bootstrap.failed` log line is
|
|
139
|
+
// emitted for observability. Audit 2026-05-23 G1.
|
|
140
|
+
try {
|
|
141
|
+
await main();
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
handleFatalBootstrapError(error, logger);
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
// Flush batched spans before the short-lived process exits — on normal
|
|
148
|
+
// completion and on handled error exits alike. No-op when telemetry was
|
|
149
|
+
// never started (standalone), so standalone runs pay nothing. The early
|
|
150
|
+
// welcome-screen `process.exit(0)` above runs no commands and emits no
|
|
151
|
+
// spans, so skipping the flush there is harmless.
|
|
152
|
+
await shutdownTelemetry();
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helper for the `--open` flag on report-producing commands.
|
|
3
|
+
*
|
|
4
|
+
* After a run completes, generate the HTML report and launch it in
|
|
5
|
+
* the default browser. Hard-skip conditions are strict: we NEVER open
|
|
6
|
+
* a browser in environments where it would be wrong (CI, non-TTY,
|
|
7
|
+
* --json output, SSH without a display).
|
|
8
|
+
*
|
|
9
|
+
* The underlying cross-platform launcher is the `open` npm package
|
|
10
|
+
* (wraps macOS `open`, Linux `xdg-open`, Windows `start`).
|
|
11
|
+
*/
|
|
12
|
+
export interface OpenReportDecision {
|
|
13
|
+
readonly shouldOpen: boolean;
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
}
|
|
16
|
+
export interface OpenReportContext {
|
|
17
|
+
readonly openRequested: boolean;
|
|
18
|
+
readonly jsonOutput: boolean;
|
|
19
|
+
readonly stdoutIsTTY: boolean;
|
|
20
|
+
readonly env: NodeJS.ProcessEnv;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Decide whether to honor a --open request. Kept pure so tests can
|
|
24
|
+
* exercise every branch without process manipulation.
|
|
25
|
+
*
|
|
26
|
+
* Skip conditions (all strict — no override):
|
|
27
|
+
* - --json set (caller wants machine output)
|
|
28
|
+
* - stdout is not a TTY (pipeline / log redirect)
|
|
29
|
+
* - CI env var set (GitHub Actions, GitLab CI, CircleCI, etc.)
|
|
30
|
+
* - SSH_CONNECTION set AND no DISPLAY/WAYLAND_DISPLAY (remote shell
|
|
31
|
+
* without a graphical session — don't try)
|
|
32
|
+
*/
|
|
33
|
+
export declare function decideReportOpen(ctx: OpenReportContext): OpenReportDecision;
|
|
34
|
+
/**
|
|
35
|
+
* Launch the given URL or file path in the default browser. Returns
|
|
36
|
+
* true on success, false if `open` refused or threw. Never propagates
|
|
37
|
+
* — a failure to open a browser should NOT fail the fitness run.
|
|
38
|
+
*/
|
|
39
|
+
export declare function launchReport(target: string): Promise<boolean>;
|
|
40
|
+
//# sourceMappingURL=open-report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-report.d.ts","sourceRoot":"","sources":["../src/open-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,kBAAkB,CAS3E;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQnE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Helper for the `--open` flag on report-producing commands.
|
|
3
|
+
*
|
|
4
|
+
* After a run completes, generate the HTML report and launch it in
|
|
5
|
+
* the default browser. Hard-skip conditions are strict: we NEVER open
|
|
6
|
+
* a browser in environments where it would be wrong (CI, non-TTY,
|
|
7
|
+
* --json output, SSH without a display).
|
|
8
|
+
*
|
|
9
|
+
* The underlying cross-platform launcher is the `open` npm package
|
|
10
|
+
* (wraps macOS `open`, Linux `xdg-open`, Windows `start`).
|
|
11
|
+
*/
|
|
12
|
+
import open from 'open';
|
|
13
|
+
/**
|
|
14
|
+
* Decide whether to honor a --open request. Kept pure so tests can
|
|
15
|
+
* exercise every branch without process manipulation.
|
|
16
|
+
*
|
|
17
|
+
* Skip conditions (all strict — no override):
|
|
18
|
+
* - --json set (caller wants machine output)
|
|
19
|
+
* - stdout is not a TTY (pipeline / log redirect)
|
|
20
|
+
* - CI env var set (GitHub Actions, GitLab CI, CircleCI, etc.)
|
|
21
|
+
* - SSH_CONNECTION set AND no DISPLAY/WAYLAND_DISPLAY (remote shell
|
|
22
|
+
* without a graphical session — don't try)
|
|
23
|
+
*/
|
|
24
|
+
export function decideReportOpen(ctx) {
|
|
25
|
+
if (!ctx.openRequested)
|
|
26
|
+
return { shouldOpen: false, reason: 'not-requested' };
|
|
27
|
+
if (ctx.jsonOutput)
|
|
28
|
+
return { shouldOpen: false, reason: 'json-mode' };
|
|
29
|
+
if (!ctx.stdoutIsTTY)
|
|
30
|
+
return { shouldOpen: false, reason: 'non-tty' };
|
|
31
|
+
if (ctx.env.CI)
|
|
32
|
+
return { shouldOpen: false, reason: 'ci-env' };
|
|
33
|
+
const ssh = ctx.env.SSH_CONNECTION ?? ctx.env.SSH_CLIENT;
|
|
34
|
+
const display = ctx.env.DISPLAY ?? ctx.env.WAYLAND_DISPLAY;
|
|
35
|
+
if (ssh && !display)
|
|
36
|
+
return { shouldOpen: false, reason: 'ssh-no-display' };
|
|
37
|
+
return { shouldOpen: true, reason: 'ok' };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Launch the given URL or file path in the default browser. Returns
|
|
41
|
+
* true on success, false if `open` refused or threw. Never propagates
|
|
42
|
+
* — a failure to open a browser should NOT fail the fitness run.
|
|
43
|
+
*/
|
|
44
|
+
export async function launchReport(target) {
|
|
45
|
+
try {
|
|
46
|
+
await open(target);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// @fitness-ignore-next-line error-handling-quality -- documented contract (see JSDoc above): failure to open a browser must NOT fail the fitness run; caller dispatches on the boolean return.
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=open-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open-report.js","sourceRoot":"","sources":["../src/open-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAcxB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAsB;IACrD,IAAI,CAAC,GAAG,CAAC,aAAa;QAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC9E,IAAI,GAAG,CAAC,UAAU;QAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACtE,IAAI,CAAC,GAAG,CAAC,WAAW;QAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACtE,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC;IACzD,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC;IAC3D,IAAI,GAAG,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC5E,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc;IAC/C,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,+LAA+L;QAC/L,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* report-compose — the cross-tool report composition root.
|
|
3
|
+
*
|
|
4
|
+
* Audit 2026-05-29 (L2): the CLI, not any single tool, composes the HTML
|
|
5
|
+
* report. It walks every registered tool's `collectReportData(scope)`
|
|
6
|
+
* contribution and merges the results into one HTML report input, then
|
|
7
|
+
* renders the self-contained HTML via `@opensip-cli/dashboard` and
|
|
8
|
+
* writes it to the project's reports directory.
|
|
9
|
+
*
|
|
10
|
+
* This is what decouples fitness from graph: fitness contributes only
|
|
11
|
+
* its own catalogs (`checkCatalog` / `recipeCatalog` / `editorProtocol`)
|
|
12
|
+
* and graph contributes only `graphCatalog`. Neither reaches into the
|
|
13
|
+
* other; the CLI owns the merge because composition needs the tool
|
|
14
|
+
* REGISTRY (`RunScope.tools`), which the tool-facing `ToolScope`
|
|
15
|
+
* deliberately excludes.
|
|
16
|
+
*
|
|
17
|
+
* Why read `currentScope()` here and nowhere in the tool packages: the
|
|
18
|
+
* `Tool` contract must not depend on `RunScope` (that would reintroduce
|
|
19
|
+
* a kernel⟷tool cycle). The CLI is the only layer allowed to read the
|
|
20
|
+
* concrete `RunScope` (which has `.tools`) — tools receive the narrower
|
|
21
|
+
* `ToolScope` view as the `collectReportData` parameter.
|
|
22
|
+
*/
|
|
23
|
+
import type { ReportResult } from '@opensip-cli/contracts';
|
|
24
|
+
/**
|
|
25
|
+
* Compose the cross-tool report, write it to
|
|
26
|
+
* `<reportsDir>/latest.html`, and (optionally) open it in the browser.
|
|
27
|
+
*
|
|
28
|
+
* Returns a `ReportResult` describing the written path and whether a
|
|
29
|
+
* browser was launched. Browser-launch failures never propagate — they
|
|
30
|
+
* fall through to `opened: false` so the user can open the file manually.
|
|
31
|
+
*/
|
|
32
|
+
export declare function composeAndWriteReport(opts: {
|
|
33
|
+
open: boolean;
|
|
34
|
+
}): Promise<ReportResult>;
|
|
35
|
+
//# sourceMappingURL=report-compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-compose.d.ts","sourceRoot":"","sources":["../src/report-compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAoBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAkE3D;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAY1F"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* report-compose — the cross-tool report composition root.
|
|
3
|
+
*
|
|
4
|
+
* Audit 2026-05-29 (L2): the CLI, not any single tool, composes the HTML
|
|
5
|
+
* report. It walks every registered tool's `collectReportData(scope)`
|
|
6
|
+
* contribution and merges the results into one HTML report input, then
|
|
7
|
+
* renders the self-contained HTML via `@opensip-cli/dashboard` and
|
|
8
|
+
* writes it to the project's reports directory.
|
|
9
|
+
*
|
|
10
|
+
* This is what decouples fitness from graph: fitness contributes only
|
|
11
|
+
* its own catalogs (`checkCatalog` / `recipeCatalog` / `editorProtocol`)
|
|
12
|
+
* and graph contributes only `graphCatalog`. Neither reaches into the
|
|
13
|
+
* other; the CLI owns the merge because composition needs the tool
|
|
14
|
+
* REGISTRY (`RunScope.tools`), which the tool-facing `ToolScope`
|
|
15
|
+
* deliberately excludes.
|
|
16
|
+
*
|
|
17
|
+
* Why read `currentScope()` here and nowhere in the tool packages: the
|
|
18
|
+
* `Tool` contract must not depend on `RunScope` (that would reintroduce
|
|
19
|
+
* a kernel⟷tool cycle). The CLI is the only layer allowed to read the
|
|
20
|
+
* concrete `RunScope` (which has `.tools`) — tools receive the narrower
|
|
21
|
+
* `ToolScope` view as the `collectReportData` parameter.
|
|
22
|
+
*/
|
|
23
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
24
|
+
import { join } from 'node:path';
|
|
25
|
+
import { currentScope, resolveProjectPaths, SystemError, logger as defaultLogger, } from '@opensip-cli/core';
|
|
26
|
+
import { generateDashboardHtml, } from '@opensip-cli/dashboard';
|
|
27
|
+
import { SessionRepo } from '@opensip-cli/session-store';
|
|
28
|
+
import { getCurrentProjectRoot } from './cli-context.js';
|
|
29
|
+
import { launchReport } from './open-report.js';
|
|
30
|
+
/**
|
|
31
|
+
* Host-reserved top-level dashboard-input key a tool's `collectReportData` must
|
|
32
|
+
* never set: `sessions` is the durable cross-tool run history the host owns. A
|
|
33
|
+
* tool that returns it is ignored (best-effort) with a warning.
|
|
34
|
+
*/
|
|
35
|
+
const RESERVED_DASHBOARD_KEYS = new Set(['sessions']);
|
|
36
|
+
/**
|
|
37
|
+
* Build the merged HTML report input from every registered tool's
|
|
38
|
+
* report-data contribution, on top of the shared session history.
|
|
39
|
+
*
|
|
40
|
+
* Sessions come from the CLI (cross-tool history); each tool's
|
|
41
|
+
* `collectReportData` returns its own keyed inputs which are merged
|
|
42
|
+
* onto the base via `Object.assign`. Contributions are best-effort: a
|
|
43
|
+
* tool that omits `collectReportData`, or returns an empty object,
|
|
44
|
+
* simply contributes nothing.
|
|
45
|
+
*
|
|
46
|
+
* @throws {Error} When called outside an entered `RunScope` (i.e. not inside
|
|
47
|
+
* a CLI action body), since session history and tool contributions both
|
|
48
|
+
* require the scope.
|
|
49
|
+
*/
|
|
50
|
+
async function composeReportInput() {
|
|
51
|
+
const scope = currentScope();
|
|
52
|
+
if (!scope) {
|
|
53
|
+
// Use a typed error with code so the top-level handler + --json paths
|
|
54
|
+
// produce a clean, consistent failure instead of a raw Error.
|
|
55
|
+
throw new SystemError('report composition requires an entered RunScope (run inside a CLI action body).', { code: 'SYSTEM.SCOPE.NOT_ENTERED' });
|
|
56
|
+
}
|
|
57
|
+
const log = scope.logger ?? defaultLogger;
|
|
58
|
+
const datastore = scope.datastore();
|
|
59
|
+
const repo = datastore ? new SessionRepo(datastore) : undefined;
|
|
60
|
+
const sessions = repo ? [...repo.list({ limit: 20 })] : [];
|
|
61
|
+
const input = { sessions };
|
|
62
|
+
for (const tool of scope.tools.list()) {
|
|
63
|
+
const contribution = await tool.collectReportData?.(scope);
|
|
64
|
+
if (contribution) {
|
|
65
|
+
// Guardrail (spec §8): tools must never clobber the host-owned `sessions`
|
|
66
|
+
// run history. Ignore with a warning (best-effort, like other contribution
|
|
67
|
+
// faults) — the host owns the cross-tool history.
|
|
68
|
+
const reserved = Object.keys(contribution).filter((k) => RESERVED_DASHBOARD_KEYS.has(k));
|
|
69
|
+
if (reserved.length > 0) {
|
|
70
|
+
void log.warn({
|
|
71
|
+
evt: 'cli.report.compose.reserved_key_ignored',
|
|
72
|
+
module: 'cli:report',
|
|
73
|
+
tool: tool.metadata.id,
|
|
74
|
+
keys: reserved,
|
|
75
|
+
msg: 'Tool collectReportData returned a reserved host key; it was ignored.',
|
|
76
|
+
});
|
|
77
|
+
for (const k of reserved)
|
|
78
|
+
delete contribution[k];
|
|
79
|
+
}
|
|
80
|
+
Object.assign(input, contribution);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return input;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Compose the cross-tool report, write it to
|
|
87
|
+
* `<reportsDir>/latest.html`, and (optionally) open it in the browser.
|
|
88
|
+
*
|
|
89
|
+
* Returns a `ReportResult` describing the written path and whether a
|
|
90
|
+
* browser was launched. Browser-launch failures never propagate — they
|
|
91
|
+
* fall through to `opened: false` so the user can open the file manually.
|
|
92
|
+
*/
|
|
93
|
+
export async function composeAndWriteReport(opts) {
|
|
94
|
+
const input = await composeReportInput();
|
|
95
|
+
const html = generateDashboardHtml(input);
|
|
96
|
+
const paths = resolveProjectPaths(getCurrentProjectRoot());
|
|
97
|
+
mkdirSync(paths.reportsDir, { recursive: true });
|
|
98
|
+
const reportPath = join(paths.reportsDir, 'latest.html');
|
|
99
|
+
writeFileSync(reportPath, html, 'utf8');
|
|
100
|
+
const opened = opts.open ? await launchReport(reportPath) : false;
|
|
101
|
+
return { type: 'report', path: reportPath, opened };
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=report-compose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-compose.js","sourceRoot":"","sources":["../src/report-compose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CommandResult, ToolSessionReplay } from '@opensip-cli/contracts';
|
|
2
|
+
import type { ToolRegistry, ToolSessionRecord, ToolShortId } from '@opensip-cli/core';
|
|
3
|
+
export interface CliSessionReplayContribution {
|
|
4
|
+
readonly tool: ToolShortId;
|
|
5
|
+
readonly replaySession: (stored: ToolSessionRecord) => ToolSessionReplay<CommandResult>;
|
|
6
|
+
}
|
|
7
|
+
export declare class SessionReplayRegistry {
|
|
8
|
+
private readonly byTool;
|
|
9
|
+
private constructor();
|
|
10
|
+
static empty(): SessionReplayRegistry;
|
|
11
|
+
/**
|
|
12
|
+
* Build the registry from the tools' `sessionReplay` contributions.
|
|
13
|
+
*
|
|
14
|
+
* @throws {Error} when two registered tools claim the same `tool` short id
|
|
15
|
+
* (a duplicate session-replay contribution).
|
|
16
|
+
*/
|
|
17
|
+
static fromTools(registry: ToolRegistry): SessionReplayRegistry;
|
|
18
|
+
get(tool: ToolShortId): CliSessionReplayContribution | undefined;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=session-replay-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-replay-registry.d.ts","sourceRoot":"","sources":["../src/session-replay-registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EAEjB,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,iBAAiB,CAAC,aAAa,CAAC,CAAC;CACzF;AAED,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,MAAM;IADzB,OAAO;IAIP,MAAM,CAAC,KAAK,IAAI,qBAAqB;IAIrC;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,YAAY,GAAG,qBAAqB;IAa/D,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,4BAA4B,GAAG,SAAS;CAGjE"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export class SessionReplayRegistry {
|
|
2
|
+
byTool;
|
|
3
|
+
constructor(byTool) {
|
|
4
|
+
this.byTool = byTool;
|
|
5
|
+
}
|
|
6
|
+
static empty() {
|
|
7
|
+
return new SessionReplayRegistry(new Map());
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Build the registry from the tools' `sessionReplay` contributions.
|
|
11
|
+
*
|
|
12
|
+
* @throws {Error} when two registered tools claim the same `tool` short id
|
|
13
|
+
* (a duplicate session-replay contribution).
|
|
14
|
+
*/
|
|
15
|
+
static fromTools(registry) {
|
|
16
|
+
const byTool = new Map();
|
|
17
|
+
for (const tool of registry.list()) {
|
|
18
|
+
const contribution = tool.sessionReplay;
|
|
19
|
+
if (contribution === undefined)
|
|
20
|
+
continue;
|
|
21
|
+
if (byTool.has(contribution.tool)) {
|
|
22
|
+
throw new Error(`Duplicate session replay contribution for tool '${contribution.tool}'`);
|
|
23
|
+
}
|
|
24
|
+
byTool.set(contribution.tool, normalizeContribution(contribution));
|
|
25
|
+
}
|
|
26
|
+
return new SessionReplayRegistry(byTool);
|
|
27
|
+
}
|
|
28
|
+
get(tool) {
|
|
29
|
+
return this.byTool.get(tool);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function normalizeContribution(contribution) {
|
|
33
|
+
return {
|
|
34
|
+
tool: contribution.tool,
|
|
35
|
+
replaySession: (stored) => contribution.replaySession(stored),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=session-replay-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-replay-registry.js","sourceRoot":"","sources":["../src/session-replay-registry.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,qBAAqB;IAEb;IADnB,YACmB,MAA8D;QAA9D,WAAM,GAAN,MAAM,CAAwD;IAC9E,CAAC;IAEJ,MAAM,CAAC,KAAK;QACV,OAAO,IAAI,qBAAqB,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,QAAsB;QACrC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA6C,CAAC;QACpE,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YACnC,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC;YACxC,IAAI,YAAY,KAAK,SAAS;gBAAE,SAAS;YACzC,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClC,MAAM,IAAI,KAAK,CAAC,mDAAmD,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC;YAC3F,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,qBAAqB,CAAC,YAAY,CAAC,CAAC,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,GAAG,CAAC,IAAiB;QACnB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CACF;AAED,SAAS,qBAAqB,CAC5B,YAA2C;IAE3C,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,IAAI;QACvB,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CACxB,YAAY,CAAC,aAAa,CAAC,MAAM,CAAqC;KACzE,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profiling support — optional and severable (see observability-hardening plan).
|
|
3
|
+
*
|
|
4
|
+
* Gate (per ADR-0049 and plan):
|
|
5
|
+
* - Recommended: OPENSIP_PROFILING=1 AND OTEL_EXPORTER_OTLP_ENDPOINT set.
|
|
6
|
+
* - Supported alternative (kept for flexibility): profiling can be tied to
|
|
7
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT alone (documented with cost warnings).
|
|
8
|
+
*
|
|
9
|
+
* Implementation uses Node's built-in `inspector` module for real CPU profiles
|
|
10
|
+
* (no extra published dependency for the optional profiling path). This gives
|
|
11
|
+
* actionable .cpuprofile files for short-lived CLI runs, with runId/command
|
|
12
|
+
* labels embedded in the filename and a sidecar JSON.
|
|
13
|
+
*
|
|
14
|
+
* When a full OTel profiles signal / Pyroscope client is desired, the start/stop
|
|
15
|
+
* hooks here are the single place to swap in that implementation while reusing
|
|
16
|
+
* the same resource attributes, runId, and shutdown discipline.
|
|
17
|
+
*
|
|
18
|
+
* The seam is intentionally thin in core; all heavy lifting and any future
|
|
19
|
+
* SDK bits stay in the CLI root.
|
|
20
|
+
*/
|
|
21
|
+
import { type RunScope } from '@opensip-cli/core';
|
|
22
|
+
export interface ProfilingLabels {
|
|
23
|
+
readonly runId?: string;
|
|
24
|
+
readonly command?: string;
|
|
25
|
+
readonly [key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** Returns true if the recommended or OTEL-only profiling gate is satisfied. */
|
|
28
|
+
export declare function isProfilingEnabled(): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Start CPU profiling for this invocation (if gate is open).
|
|
31
|
+
* Must be called after RunScope is entered (so runId is available).
|
|
32
|
+
* Safe to call multiple times (idempotent).
|
|
33
|
+
*/
|
|
34
|
+
export declare function startProfiling(scope?: RunScope, command?: string): void;
|
|
35
|
+
/**
|
|
36
|
+
* Stop profiling and flush the .cpuprofile + labels sidecar.
|
|
37
|
+
* Safe and idempotent.
|
|
38
|
+
*/
|
|
39
|
+
export declare function stopProfiling(): void;
|
|
40
|
+
/** Exposed for tests / shutdown. */
|
|
41
|
+
export declare function resetProfilingForTests(): void;
|
|
42
|
+
//# sourceMappingURL=profiling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiling.d.ts","sourceRoot":"","sources":["../../src/telemetry/profiling.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAY1D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,gFAAgF;AAChF,wBAAgB,kBAAkB,IAAI,OAAO,CAW5C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAuDvE;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAuCpC;AAgBD,oCAAoC;AACpC,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
|