@opensip-cli/core 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 +31 -0
- package/dist/__tests__/config-resolution.test.d.ts +2 -0
- package/dist/__tests__/config-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/config-resolution.test.js +94 -0
- package/dist/__tests__/config-resolution.test.js.map +1 -0
- package/dist/__tests__/public-api.test.d.ts +16 -0
- package/dist/__tests__/public-api.test.d.ts.map +1 -0
- package/dist/__tests__/public-api.test.js +209 -0
- package/dist/__tests__/public-api.test.js.map +1 -0
- package/dist/__tests__/signal-batch.test.d.ts +2 -0
- package/dist/__tests__/signal-batch.test.d.ts.map +1 -0
- package/dist/__tests__/signal-batch.test.js +39 -0
- package/dist/__tests__/signal-batch.test.js.map +1 -0
- package/dist/__tests__/signal-sink.test.d.ts +2 -0
- package/dist/__tests__/signal-sink.test.d.ts.map +1 -0
- package/dist/__tests__/signal-sink.test.js +25 -0
- package/dist/__tests__/signal-sink.test.js.map +1 -0
- package/dist/__tests__/strip-utils.test.d.ts +2 -0
- package/dist/__tests__/strip-utils.test.d.ts.map +1 -0
- package/dist/__tests__/strip-utils.test.js +397 -0
- package/dist/__tests__/strip-utils.test.js.map +1 -0
- package/dist/__tests__/text-tree.test.d.ts +2 -0
- package/dist/__tests__/text-tree.test.d.ts.map +1 -0
- package/dist/__tests__/text-tree.test.js +31 -0
- package/dist/__tests__/text-tree.test.js.map +1 -0
- package/dist/baseline/__tests__/fingerprint-strategy.test.d.ts +2 -0
- package/dist/baseline/__tests__/fingerprint-strategy.test.d.ts.map +1 -0
- package/dist/baseline/__tests__/fingerprint-strategy.test.js +69 -0
- package/dist/baseline/__tests__/fingerprint-strategy.test.js.map +1 -0
- package/dist/baseline/fingerprint-strategy.d.ts +70 -0
- package/dist/baseline/fingerprint-strategy.d.ts.map +1 -0
- package/dist/baseline/fingerprint-strategy.js +90 -0
- package/dist/baseline/fingerprint-strategy.js.map +1 -0
- package/dist/config-resolution.d.ts +27 -0
- package/dist/config-resolution.d.ts.map +1 -0
- package/dist/config-resolution.js +92 -0
- package/dist/config-resolution.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/__tests__/content-filter-dispatch.test.d.ts +2 -0
- package/dist/languages/__tests__/content-filter-dispatch.test.d.ts.map +1 -0
- package/dist/languages/__tests__/content-filter-dispatch.test.js +87 -0
- package/dist/languages/__tests__/content-filter-dispatch.test.js.map +1 -0
- package/dist/languages/__tests__/non-code-formats.test.d.ts +2 -0
- package/dist/languages/__tests__/non-code-formats.test.d.ts.map +1 -0
- package/dist/languages/__tests__/non-code-formats.test.js +31 -0
- package/dist/languages/__tests__/non-code-formats.test.js.map +1 -0
- package/dist/languages/__tests__/parse-cache.test.d.ts +2 -0
- package/dist/languages/__tests__/parse-cache.test.d.ts.map +1 -0
- package/dist/languages/__tests__/parse-cache.test.js +228 -0
- package/dist/languages/__tests__/parse-cache.test.js.map +1 -0
- package/dist/languages/__tests__/registry.test.d.ts +2 -0
- package/dist/languages/__tests__/registry.test.d.ts.map +1 -0
- package/dist/languages/__tests__/registry.test.js +193 -0
- package/dist/languages/__tests__/registry.test.js.map +1 -0
- package/dist/languages/__tests__/workspace-unit-contract.test.d.ts +2 -0
- package/dist/languages/__tests__/workspace-unit-contract.test.d.ts.map +1 -0
- package/dist/languages/__tests__/workspace-unit-contract.test.js +66 -0
- package/dist/languages/__tests__/workspace-unit-contract.test.js.map +1 -0
- package/dist/languages/adapter.d.ts +66 -0
- package/dist/languages/adapter.d.ts.map +1 -0
- package/dist/languages/adapter.js +2 -0
- package/dist/languages/adapter.js.map +1 -0
- package/dist/languages/content-filter-dispatch.d.ts +36 -0
- package/dist/languages/content-filter-dispatch.d.ts.map +1 -0
- package/dist/languages/content-filter-dispatch.js +75 -0
- package/dist/languages/content-filter-dispatch.js.map +1 -0
- package/dist/languages/generic-types.d.ts +22 -0
- package/dist/languages/generic-types.d.ts.map +1 -0
- package/dist/languages/generic-types.js +3 -0
- package/dist/languages/generic-types.js.map +1 -0
- package/dist/languages/index.d.ts +12 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +7 -0
- package/dist/languages/index.js.map +1 -0
- package/dist/languages/non-code-formats.d.ts +37 -0
- package/dist/languages/non-code-formats.d.ts.map +1 -0
- package/dist/languages/non-code-formats.js +45 -0
- package/dist/languages/non-code-formats.js.map +1 -0
- package/dist/languages/parse-cache-class.d.ts +69 -0
- package/dist/languages/parse-cache-class.d.ts.map +1 -0
- package/dist/languages/parse-cache-class.js +135 -0
- package/dist/languages/parse-cache-class.js.map +1 -0
- package/dist/languages/parse-cache.d.ts +54 -0
- package/dist/languages/parse-cache.d.ts.map +1 -0
- package/dist/languages/parse-cache.js +88 -0
- package/dist/languages/parse-cache.js.map +1 -0
- package/dist/languages/registry.d.ts +35 -0
- package/dist/languages/registry.d.ts.map +1 -0
- package/dist/languages/registry.js +123 -0
- package/dist/languages/registry.js.map +1 -0
- package/dist/languages/strip-scanners.d.ts +170 -0
- package/dist/languages/strip-scanners.d.ts.map +1 -0
- package/dist/languages/strip-scanners.js +233 -0
- package/dist/languages/strip-scanners.js.map +1 -0
- package/dist/languages/strip-utils.d.ts +66 -0
- package/dist/languages/strip-utils.d.ts.map +1 -0
- package/dist/languages/strip-utils.js +88 -0
- package/dist/languages/strip-utils.js.map +1 -0
- package/dist/languages/text-tree.d.ts +44 -0
- package/dist/languages/text-tree.d.ts.map +1 -0
- package/dist/languages/text-tree.js +34 -0
- package/dist/languages/text-tree.js.map +1 -0
- package/dist/languages/workspace-unit.d.ts +18 -0
- package/dist/languages/workspace-unit.d.ts.map +1 -0
- package/dist/languages/workspace-unit.js +2 -0
- package/dist/languages/workspace-unit.js.map +1 -0
- package/dist/lib/__tests__/config-version.test.d.ts +12 -0
- package/dist/lib/__tests__/config-version.test.d.ts.map +1 -0
- package/dist/lib/__tests__/config-version.test.js +92 -0
- package/dist/lib/__tests__/config-version.test.js.map +1 -0
- package/dist/lib/__tests__/diagnostics-bus.test.d.ts +7 -0
- package/dist/lib/__tests__/diagnostics-bus.test.d.ts.map +1 -0
- package/dist/lib/__tests__/diagnostics-bus.test.js +44 -0
- package/dist/lib/__tests__/diagnostics-bus.test.js.map +1 -0
- package/dist/lib/__tests__/env-registry.test.d.ts +7 -0
- package/dist/lib/__tests__/env-registry.test.d.ts.map +1 -0
- package/dist/lib/__tests__/env-registry.test.js +82 -0
- package/dist/lib/__tests__/env-registry.test.js.map +1 -0
- package/dist/lib/__tests__/errors.test.d.ts +2 -0
- package/dist/lib/__tests__/errors.test.d.ts.map +1 -0
- package/dist/lib/__tests__/errors.test.js +218 -0
- package/dist/lib/__tests__/errors.test.js.map +1 -0
- package/dist/lib/__tests__/format.test.d.ts +2 -0
- package/dist/lib/__tests__/format.test.d.ts.map +1 -0
- package/dist/lib/__tests__/format.test.js +23 -0
- package/dist/lib/__tests__/format.test.js.map +1 -0
- package/dist/lib/__tests__/ids.test.d.ts +2 -0
- package/dist/lib/__tests__/ids.test.d.ts.map +1 -0
- package/dist/lib/__tests__/ids.test.js +80 -0
- package/dist/lib/__tests__/ids.test.js.map +1 -0
- package/dist/lib/__tests__/logger.test.d.ts +2 -0
- package/dist/lib/__tests__/logger.test.d.ts.map +1 -0
- package/dist/lib/__tests__/logger.test.js +284 -0
- package/dist/lib/__tests__/logger.test.js.map +1 -0
- package/dist/lib/__tests__/package-version.test.d.ts +2 -0
- package/dist/lib/__tests__/package-version.test.d.ts.map +1 -0
- package/dist/lib/__tests__/package-version.test.js +47 -0
- package/dist/lib/__tests__/package-version.test.js.map +1 -0
- package/dist/lib/__tests__/paths.test.d.ts +5 -0
- package/dist/lib/__tests__/paths.test.d.ts.map +1 -0
- package/dist/lib/__tests__/paths.test.js +59 -0
- package/dist/lib/__tests__/paths.test.js.map +1 -0
- package/dist/lib/__tests__/payload-version.test.d.ts +2 -0
- package/dist/lib/__tests__/payload-version.test.d.ts.map +1 -0
- package/dist/lib/__tests__/payload-version.test.js +35 -0
- package/dist/lib/__tests__/payload-version.test.js.map +1 -0
- package/dist/lib/__tests__/phantom-detect.test.d.ts +10 -0
- package/dist/lib/__tests__/phantom-detect.test.d.ts.map +1 -0
- package/dist/lib/__tests__/phantom-detect.test.js +84 -0
- package/dist/lib/__tests__/phantom-detect.test.js.map +1 -0
- package/dist/lib/__tests__/project-context.test.d.ts +10 -0
- package/dist/lib/__tests__/project-context.test.d.ts.map +1 -0
- package/dist/lib/__tests__/project-context.test.js +240 -0
- package/dist/lib/__tests__/project-context.test.js.map +1 -0
- package/dist/lib/__tests__/registry.test.d.ts +2 -0
- package/dist/lib/__tests__/registry.test.d.ts.map +1 -0
- package/dist/lib/__tests__/registry.test.js +333 -0
- package/dist/lib/__tests__/registry.test.js.map +1 -0
- package/dist/lib/__tests__/retry.test.d.ts +2 -0
- package/dist/lib/__tests__/retry.test.d.ts.map +1 -0
- package/dist/lib/__tests__/retry.test.js +71 -0
- package/dist/lib/__tests__/retry.test.js.map +1 -0
- package/dist/lib/__tests__/run-diagnostics.test.d.ts +9 -0
- package/dist/lib/__tests__/run-diagnostics.test.d.ts.map +1 -0
- package/dist/lib/__tests__/run-diagnostics.test.js +61 -0
- package/dist/lib/__tests__/run-diagnostics.test.js.map +1 -0
- package/dist/lib/__tests__/run-scope.test.d.ts +2 -0
- package/dist/lib/__tests__/run-scope.test.d.ts.map +1 -0
- package/dist/lib/__tests__/run-scope.test.js +202 -0
- package/dist/lib/__tests__/run-scope.test.js.map +1 -0
- package/dist/lib/__tests__/run-timer.test.d.ts +2 -0
- package/dist/lib/__tests__/run-timer.test.d.ts.map +1 -0
- package/dist/lib/__tests__/run-timer.test.js +152 -0
- package/dist/lib/__tests__/run-timer.test.js.map +1 -0
- package/dist/lib/__tests__/severity-policy.test.d.ts +6 -0
- package/dist/lib/__tests__/severity-policy.test.d.ts.map +1 -0
- package/dist/lib/__tests__/severity-policy.test.js +47 -0
- package/dist/lib/__tests__/severity-policy.test.js.map +1 -0
- package/dist/lib/__tests__/telemetry.test.d.ts +2 -0
- package/dist/lib/__tests__/telemetry.test.d.ts.map +1 -0
- package/dist/lib/__tests__/telemetry.test.js +212 -0
- package/dist/lib/__tests__/telemetry.test.js.map +1 -0
- package/dist/lib/__tests__/verdict-policy.test.d.ts +7 -0
- package/dist/lib/__tests__/verdict-policy.test.d.ts.map +1 -0
- package/dist/lib/__tests__/verdict-policy.test.js +91 -0
- package/dist/lib/__tests__/verdict-policy.test.js.map +1 -0
- package/dist/lib/__tests__/yaml.test.d.ts +6 -0
- package/dist/lib/__tests__/yaml.test.d.ts.map +1 -0
- package/dist/lib/__tests__/yaml.test.js +79 -0
- package/dist/lib/__tests__/yaml.test.js.map +1 -0
- package/dist/lib/config-version.d.ts +49 -0
- package/dist/lib/config-version.d.ts.map +1 -0
- package/dist/lib/config-version.js +56 -0
- package/dist/lib/config-version.js.map +1 -0
- package/dist/lib/diagnostics-bus.d.ts +48 -0
- package/dist/lib/diagnostics-bus.d.ts.map +1 -0
- package/dist/lib/diagnostics-bus.js +74 -0
- package/dist/lib/diagnostics-bus.js.map +1 -0
- package/dist/lib/env-registry.d.ts +108 -0
- package/dist/lib/env-registry.d.ts.map +1 -0
- package/dist/lib/env-registry.js +92 -0
- package/dist/lib/env-registry.js.map +1 -0
- package/dist/lib/errors.d.ts +132 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +160 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/execution/__tests__/execution.test.d.ts +7 -0
- package/dist/lib/execution/__tests__/execution.test.d.ts.map +1 -0
- package/dist/lib/execution/__tests__/execution.test.js +254 -0
- package/dist/lib/execution/__tests__/execution.test.js.map +1 -0
- package/dist/lib/execution/index.d.ts +15 -0
- package/dist/lib/execution/index.d.ts.map +1 -0
- package/dist/lib/execution/index.js +10 -0
- package/dist/lib/execution/index.js.map +1 -0
- package/dist/lib/execution/options.d.ts +32 -0
- package/dist/lib/execution/options.d.ts.map +1 -0
- package/dist/lib/execution/options.js +15 -0
- package/dist/lib/execution/options.js.map +1 -0
- package/dist/lib/execution/pipeline.d.ts +36 -0
- package/dist/lib/execution/pipeline.d.ts.map +1 -0
- package/dist/lib/execution/pipeline.js +38 -0
- package/dist/lib/execution/pipeline.js.map +1 -0
- package/dist/lib/execution/retry.d.ts +38 -0
- package/dist/lib/execution/retry.d.ts.map +1 -0
- package/dist/lib/execution/retry.js +56 -0
- package/dist/lib/execution/retry.js.map +1 -0
- package/dist/lib/execution/run-with-timeout.d.ts +46 -0
- package/dist/lib/execution/run-with-timeout.d.ts.map +1 -0
- package/dist/lib/execution/run-with-timeout.js +86 -0
- package/dist/lib/execution/run-with-timeout.js.map +1 -0
- package/dist/lib/execution/schedule.d.ts +62 -0
- package/dist/lib/execution/schedule.d.ts.map +1 -0
- package/dist/lib/execution/schedule.js +130 -0
- package/dist/lib/execution/schedule.js.map +1 -0
- package/dist/lib/format.d.ts +17 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +26 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/ids.d.ts +13 -0
- package/dist/lib/ids.d.ts.map +1 -0
- package/dist/lib/ids.js +48 -0
- package/dist/lib/ids.js.map +1 -0
- package/dist/lib/logger.d.ts +166 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +283 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/package-version.d.ts +17 -0
- package/dist/lib/package-version.d.ts.map +1 -0
- package/dist/lib/package-version.js +52 -0
- package/dist/lib/package-version.js.map +1 -0
- package/dist/lib/paths.d.ts +139 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +105 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/payload-version.d.ts +15 -0
- package/dist/lib/payload-version.d.ts.map +1 -0
- package/dist/lib/payload-version.js +24 -0
- package/dist/lib/payload-version.js.map +1 -0
- package/dist/lib/phantom-detect.d.ts +21 -0
- package/dist/lib/phantom-detect.d.ts.map +1 -0
- package/dist/lib/phantom-detect.js +76 -0
- package/dist/lib/phantom-detect.js.map +1 -0
- package/dist/lib/project-context.d.ts +66 -0
- package/dist/lib/project-context.d.ts.map +1 -0
- package/dist/lib/project-context.js +112 -0
- package/dist/lib/project-context.js.map +1 -0
- package/dist/lib/recipe-id.d.ts +13 -0
- package/dist/lib/recipe-id.d.ts.map +1 -0
- package/dist/lib/recipe-id.js +15 -0
- package/dist/lib/recipe-id.js.map +1 -0
- package/dist/lib/registry.d.ts +98 -0
- package/dist/lib/registry.d.ts.map +1 -0
- package/dist/lib/registry.js +152 -0
- package/dist/lib/registry.js.map +1 -0
- package/dist/lib/retry.d.ts +26 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +48 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/run-diagnostics.d.ts +64 -0
- package/dist/lib/run-diagnostics.d.ts.map +1 -0
- package/dist/lib/run-diagnostics.js +25 -0
- package/dist/lib/run-diagnostics.js.map +1 -0
- package/dist/lib/run-scope.d.ts +167 -0
- package/dist/lib/run-scope.d.ts.map +1 -0
- package/dist/lib/run-scope.js +176 -0
- package/dist/lib/run-scope.js.map +1 -0
- package/dist/lib/run-timer.d.ts +82 -0
- package/dist/lib/run-timer.d.ts.map +1 -0
- package/dist/lib/run-timer.js +79 -0
- package/dist/lib/run-timer.js.map +1 -0
- package/dist/lib/scope-types.d.ts +172 -0
- package/dist/lib/scope-types.d.ts.map +1 -0
- package/dist/lib/scope-types.js +27 -0
- package/dist/lib/scope-types.js.map +1 -0
- package/dist/lib/severity-policy.d.ts +38 -0
- package/dist/lib/severity-policy.d.ts.map +1 -0
- package/dist/lib/severity-policy.js +44 -0
- package/dist/lib/severity-policy.js.map +1 -0
- package/dist/lib/telemetry.d.ts +93 -0
- package/dist/lib/telemetry.d.ts.map +1 -0
- package/dist/lib/telemetry.js +144 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/ui-context.d.ts +34 -0
- package/dist/lib/ui-context.d.ts.map +1 -0
- package/dist/lib/ui-context.js +16 -0
- package/dist/lib/ui-context.js.map +1 -0
- package/dist/lib/verdict-policy.d.ts +71 -0
- package/dist/lib/verdict-policy.d.ts.map +1 -0
- package/dist/lib/verdict-policy.js +82 -0
- package/dist/lib/verdict-policy.js.map +1 -0
- package/dist/lib/yaml.d.ts +74 -0
- package/dist/lib/yaml.d.ts.map +1 -0
- package/dist/lib/yaml.js +118 -0
- package/dist/lib/yaml.js.map +1 -0
- package/dist/plugins/__tests__/as-if-external.test.d.ts +18 -0
- package/dist/plugins/__tests__/as-if-external.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/as-if-external.test.js +159 -0
- package/dist/plugins/__tests__/as-if-external.test.js.map +1 -0
- package/dist/plugins/__tests__/authored-tool-discovery.test.d.ts +8 -0
- package/dist/plugins/__tests__/authored-tool-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/authored-tool-discovery.test.js +97 -0
- package/dist/plugins/__tests__/authored-tool-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/capability-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/capability-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/capability-discovery.test.js +349 -0
- package/dist/plugins/__tests__/capability-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/capability-from-manifest.test.d.ts +2 -0
- package/dist/plugins/__tests__/capability-from-manifest.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/capability-from-manifest.test.js +172 -0
- package/dist/plugins/__tests__/capability-from-manifest.test.js.map +1 -0
- package/dist/plugins/__tests__/capability-loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/capability-loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/capability-loader.test.js +122 -0
- package/dist/plugins/__tests__/capability-loader.test.js.map +1 -0
- package/dist/plugins/__tests__/capability-registry.test.d.ts +2 -0
- package/dist/plugins/__tests__/capability-registry.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/capability-registry.test.js +185 -0
- package/dist/plugins/__tests__/capability-registry.test.js.map +1 -0
- package/dist/plugins/__tests__/discover.test.d.ts +2 -0
- package/dist/plugins/__tests__/discover.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/discover.test.js +311 -0
- package/dist/plugins/__tests__/discover.test.js.map +1 -0
- package/dist/plugins/__tests__/loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/loader.test.js +191 -0
- package/dist/plugins/__tests__/loader.test.js.map +1 -0
- package/dist/plugins/__tests__/manifest-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/manifest-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/manifest-discovery.test.js +132 -0
- package/dist/plugins/__tests__/manifest-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/manifest-loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/manifest-loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/manifest-loader.test.js +434 -0
- package/dist/plugins/__tests__/manifest-loader.test.js.map +1 -0
- package/dist/plugins/__tests__/marker-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/marker-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/marker-discovery.test.js +164 -0
- package/dist/plugins/__tests__/marker-discovery.test.js.map +1 -0
- package/dist/plugins/__tests__/node-modules-walk.test.d.ts +2 -0
- package/dist/plugins/__tests__/node-modules-walk.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/node-modules-walk.test.js +76 -0
- package/dist/plugins/__tests__/node-modules-walk.test.js.map +1 -0
- package/dist/plugins/__tests__/package-entry.test.d.ts +9 -0
- package/dist/plugins/__tests__/package-entry.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/package-entry.test.js +117 -0
- package/dist/plugins/__tests__/package-entry.test.js.map +1 -0
- package/dist/plugins/__tests__/recipe-loader.test.d.ts +2 -0
- package/dist/plugins/__tests__/recipe-loader.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/recipe-loader.test.js +130 -0
- package/dist/plugins/__tests__/recipe-loader.test.js.map +1 -0
- package/dist/plugins/__tests__/scope-validation.test.d.ts +2 -0
- package/dist/plugins/__tests__/scope-validation.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/scope-validation.test.js +68 -0
- package/dist/plugins/__tests__/scope-validation.test.js.map +1 -0
- package/dist/plugins/__tests__/single-core-guard.test.d.ts +10 -0
- package/dist/plugins/__tests__/single-core-guard.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/single-core-guard.test.js +89 -0
- package/dist/plugins/__tests__/single-core-guard.test.js.map +1 -0
- package/dist/plugins/__tests__/tool-package-discovery.test.d.ts +2 -0
- package/dist/plugins/__tests__/tool-package-discovery.test.d.ts.map +1 -0
- package/dist/plugins/__tests__/tool-package-discovery.test.js +215 -0
- package/dist/plugins/__tests__/tool-package-discovery.test.js.map +1 -0
- package/dist/plugins/authored-tool-discovery.d.ts +45 -0
- package/dist/plugins/authored-tool-discovery.d.ts.map +1 -0
- package/dist/plugins/authored-tool-discovery.js +61 -0
- package/dist/plugins/authored-tool-discovery.js.map +1 -0
- package/dist/plugins/capability-discovery.d.ts +80 -0
- package/dist/plugins/capability-discovery.d.ts.map +1 -0
- package/dist/plugins/capability-discovery.js +278 -0
- package/dist/plugins/capability-discovery.js.map +1 -0
- package/dist/plugins/capability-loader.d.ts +50 -0
- package/dist/plugins/capability-loader.d.ts.map +1 -0
- package/dist/plugins/capability-loader.js +85 -0
- package/dist/plugins/capability-loader.js.map +1 -0
- package/dist/plugins/capability-registry.d.ts +169 -0
- package/dist/plugins/capability-registry.d.ts.map +1 -0
- package/dist/plugins/capability-registry.js +319 -0
- package/dist/plugins/capability-registry.js.map +1 -0
- package/dist/plugins/discover.d.ts +64 -0
- package/dist/plugins/discover.d.ts.map +1 -0
- package/dist/plugins/discover.js +303 -0
- package/dist/plugins/discover.js.map +1 -0
- package/dist/plugins/index.d.ts +37 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +40 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/json-guards.d.ts +11 -0
- package/dist/plugins/json-guards.d.ts.map +1 -0
- package/dist/plugins/json-guards.js +15 -0
- package/dist/plugins/json-guards.js.map +1 -0
- package/dist/plugins/loader.d.ts +67 -0
- package/dist/plugins/loader.d.ts.map +1 -0
- package/dist/plugins/loader.js +137 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/manifest-discovery.d.ts +28 -0
- package/dist/plugins/manifest-discovery.d.ts.map +1 -0
- package/dist/plugins/manifest-discovery.js +103 -0
- package/dist/plugins/manifest-discovery.js.map +1 -0
- package/dist/plugins/manifest-loader.d.ts +120 -0
- package/dist/plugins/manifest-loader.d.ts.map +1 -0
- package/dist/plugins/manifest-loader.js +410 -0
- package/dist/plugins/manifest-loader.js.map +1 -0
- package/dist/plugins/marker-discovery.d.ts +115 -0
- package/dist/plugins/marker-discovery.d.ts.map +1 -0
- package/dist/plugins/marker-discovery.js +172 -0
- package/dist/plugins/marker-discovery.js.map +1 -0
- package/dist/plugins/node-modules-walk.d.ts +61 -0
- package/dist/plugins/node-modules-walk.d.ts.map +1 -0
- package/dist/plugins/node-modules-walk.js +99 -0
- package/dist/plugins/node-modules-walk.js.map +1 -0
- package/dist/plugins/package-entry.d.ts +38 -0
- package/dist/plugins/package-entry.d.ts.map +1 -0
- package/dist/plugins/package-entry.js +86 -0
- package/dist/plugins/package-entry.js.map +1 -0
- package/dist/plugins/recipe-loader.d.ts +63 -0
- package/dist/plugins/recipe-loader.d.ts.map +1 -0
- package/dist/plugins/recipe-loader.js +67 -0
- package/dist/plugins/recipe-loader.js.map +1 -0
- package/dist/plugins/scope-validation.d.ts +35 -0
- package/dist/plugins/scope-validation.d.ts.map +1 -0
- package/dist/plugins/scope-validation.js +55 -0
- package/dist/plugins/scope-validation.js.map +1 -0
- package/dist/plugins/single-core-guard.d.ts +28 -0
- package/dist/plugins/single-core-guard.d.ts.map +1 -0
- package/dist/plugins/single-core-guard.js +69 -0
- package/dist/plugins/single-core-guard.js.map +1 -0
- package/dist/plugins/tool-package-discovery.d.ts +93 -0
- package/dist/plugins/tool-package-discovery.d.ts.map +1 -0
- package/dist/plugins/tool-package-discovery.js +118 -0
- package/dist/plugins/tool-package-discovery.js.map +1 -0
- package/dist/plugins/types.d.ts +78 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +15 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/recipes/__tests__/registry.test.d.ts +2 -0
- package/dist/recipes/__tests__/registry.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/registry.test.js +170 -0
- package/dist/recipes/__tests__/registry.test.js.map +1 -0
- package/dist/recipes/__tests__/selector.test.d.ts +20 -0
- package/dist/recipes/__tests__/selector.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/selector.test.js +173 -0
- package/dist/recipes/__tests__/selector.test.js.map +1 -0
- package/dist/recipes/__tests__/unit-config.test.d.ts +7 -0
- package/dist/recipes/__tests__/unit-config.test.d.ts.map +1 -0
- package/dist/recipes/__tests__/unit-config.test.js +52 -0
- package/dist/recipes/__tests__/unit-config.test.js.map +1 -0
- package/dist/recipes/registry.d.ts +105 -0
- package/dist/recipes/registry.d.ts.map +1 -0
- package/dist/recipes/registry.js +141 -0
- package/dist/recipes/registry.js.map +1 -0
- package/dist/recipes/selector.d.ts +112 -0
- package/dist/recipes/selector.d.ts.map +1 -0
- package/dist/recipes/selector.js +134 -0
- package/dist/recipes/selector.js.map +1 -0
- package/dist/recipes/unit-config.d.ts +63 -0
- package/dist/recipes/unit-config.d.ts.map +1 -0
- package/dist/recipes/unit-config.js +68 -0
- package/dist/recipes/unit-config.js.map +1 -0
- package/dist/runtime/__tests__/in-process-transport.test.d.ts +6 -0
- package/dist/runtime/__tests__/in-process-transport.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/in-process-transport.test.js +73 -0
- package/dist/runtime/__tests__/in-process-transport.test.js.map +1 -0
- package/dist/runtime/__tests__/subprocess-transport.test.d.ts +11 -0
- package/dist/runtime/__tests__/subprocess-transport.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/subprocess-transport.test.js +118 -0
- package/dist/runtime/__tests__/subprocess-transport.test.js.map +1 -0
- package/dist/runtime/in-process-transport.d.ts +20 -0
- package/dist/runtime/in-process-transport.d.ts.map +1 -0
- package/dist/runtime/in-process-transport.js +49 -0
- package/dist/runtime/in-process-transport.js.map +1 -0
- package/dist/runtime/progress-transport.d.ts +73 -0
- package/dist/runtime/progress-transport.d.ts.map +1 -0
- package/dist/runtime/progress-transport.js +17 -0
- package/dist/runtime/progress-transport.js.map +1 -0
- package/dist/runtime/subprocess-transport.d.ts +43 -0
- package/dist/runtime/subprocess-transport.d.ts.map +1 -0
- package/dist/runtime/subprocess-transport.js +134 -0
- package/dist/runtime/subprocess-transport.js.map +1 -0
- package/dist/signals/comment-openers.d.ts +29 -0
- package/dist/signals/comment-openers.d.ts.map +1 -0
- package/dist/signals/comment-openers.js +41 -0
- package/dist/signals/comment-openers.js.map +1 -0
- package/dist/signals/comment-openers.test.d.ts +7 -0
- package/dist/signals/comment-openers.test.d.ts.map +1 -0
- package/dist/signals/comment-openers.test.js +41 -0
- package/dist/signals/comment-openers.test.js.map +1 -0
- package/dist/signals/create-signal-from-violation.d.ts +29 -0
- package/dist/signals/create-signal-from-violation.d.ts.map +1 -0
- package/dist/signals/create-signal-from-violation.js +29 -0
- package/dist/signals/create-signal-from-violation.js.map +1 -0
- package/dist/signals/signal-sink.d.ts +49 -0
- package/dist/signals/signal-sink.d.ts.map +1 -0
- package/dist/signals/signal-sink.js +6 -0
- package/dist/signals/signal-sink.js.map +1 -0
- package/dist/signals/suppress.d.ts +102 -0
- package/dist/signals/suppress.d.ts.map +1 -0
- package/dist/signals/suppress.js +325 -0
- package/dist/signals/suppress.js.map +1 -0
- package/dist/signals/suppress.test.d.ts +2 -0
- package/dist/signals/suppress.test.d.ts.map +1 -0
- package/dist/signals/suppress.test.js +213 -0
- package/dist/signals/suppress.test.js.map +1 -0
- package/dist/tools/__tests__/command-spec.test.d.ts +2 -0
- package/dist/tools/__tests__/command-spec.test.d.ts.map +1 -0
- package/dist/tools/__tests__/command-spec.test.js +191 -0
- package/dist/tools/__tests__/command-spec.test.js.map +1 -0
- package/dist/tools/__tests__/compatibility.test.d.ts +5 -0
- package/dist/tools/__tests__/compatibility.test.d.ts.map +1 -0
- package/dist/tools/__tests__/compatibility.test.js +41 -0
- package/dist/tools/__tests__/compatibility.test.js.map +1 -0
- package/dist/tools/__tests__/ids.test.d.ts +5 -0
- package/dist/tools/__tests__/ids.test.d.ts.map +1 -0
- package/dist/tools/__tests__/ids.test.js +56 -0
- package/dist/tools/__tests__/ids.test.js.map +1 -0
- package/dist/tools/__tests__/manifest-assert.test.d.ts +5 -0
- package/dist/tools/__tests__/manifest-assert.test.d.ts.map +1 -0
- package/dist/tools/__tests__/manifest-assert.test.js +66 -0
- package/dist/tools/__tests__/manifest-assert.test.js.map +1 -0
- package/dist/tools/__tests__/registry.test.d.ts +2 -0
- package/dist/tools/__tests__/registry.test.d.ts.map +1 -0
- package/dist/tools/__tests__/registry.test.js +93 -0
- package/dist/tools/__tests__/registry.test.js.map +1 -0
- package/dist/tools/__tests__/types.test.d.ts +2 -0
- package/dist/tools/__tests__/types.test.d.ts.map +1 -0
- package/dist/tools/__tests__/types.test.js +51 -0
- package/dist/tools/__tests__/types.test.js.map +1 -0
- package/dist/tools/capability.d.ts +257 -0
- package/dist/tools/capability.d.ts.map +1 -0
- package/dist/tools/capability.js +46 -0
- package/dist/tools/capability.js.map +1 -0
- package/dist/tools/command-spec.d.ts +211 -0
- package/dist/tools/command-spec.d.ts.map +1 -0
- package/dist/tools/command-spec.js +110 -0
- package/dist/tools/command-spec.js.map +1 -0
- package/dist/tools/compatibility.d.ts +45 -0
- package/dist/tools/compatibility.d.ts.map +1 -0
- package/dist/tools/compatibility.js +49 -0
- package/dist/tools/compatibility.js.map +1 -0
- package/dist/tools/ids.d.ts +61 -0
- package/dist/tools/ids.d.ts.map +1 -0
- package/dist/tools/ids.js +61 -0
- package/dist/tools/ids.js.map +1 -0
- package/dist/tools/index.d.ts +22 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +28 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/manifest-assert.d.ts +35 -0
- package/dist/tools/manifest-assert.d.ts.map +1 -0
- package/dist/tools/manifest-assert.js +67 -0
- package/dist/tools/manifest-assert.js.map +1 -0
- package/dist/tools/manifest.d.ts +178 -0
- package/dist/tools/manifest.d.ts.map +1 -0
- package/dist/tools/manifest.js +35 -0
- package/dist/tools/manifest.js.map +1 -0
- package/dist/tools/registry.d.ts +37 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +49 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +1021 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +77 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types/__tests__/signal.test.d.ts +2 -0
- package/dist/types/__tests__/signal.test.d.ts.map +1 -0
- package/dist/types/__tests__/signal.test.js +111 -0
- package/dist/types/__tests__/signal.test.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/signal-batch.d.ts +56 -0
- package/dist/types/signal-batch.d.ts.map +1 -0
- package/dist/types/signal-batch.js +54 -0
- package/dist/types/signal-batch.js.map +1 -0
- package/dist/types/signal.d.ts +77 -0
- package/dist/types/signal.d.ts.map +1 -0
- package/dist/types/signal.js +42 -0
- package/dist/types/signal.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool plugin contract.
|
|
3
|
+
*
|
|
4
|
+
* A Tool is a self-contained capability (fitness, simulation, future
|
|
5
|
+
* audit/lint/etc.) that contributes one or more CLI subcommands. The
|
|
6
|
+
* CLI is a generic dispatcher that walks the registered tool list and
|
|
7
|
+
* mounts each tool's declared `commandSpecs`.
|
|
8
|
+
*
|
|
9
|
+
* Tools are first-party (declared as a direct dep of opensip-cli)
|
|
10
|
+
* or third-party (any npm package whose package.json declares
|
|
11
|
+
* `opensipTools.kind === 'tool'` — discovered via tool-package-discovery).
|
|
12
|
+
*
|
|
13
|
+
* Contract:
|
|
14
|
+
* - `commands[]` carries metadata only (name + description, used for
|
|
15
|
+
* `--help` listings and conflict detection).
|
|
16
|
+
* - The actual subcommand wiring is host-owned: the tool declares typed
|
|
17
|
+
* `commandSpecs` and the host's `mountCommandSpec` mounts each one
|
|
18
|
+
* (1.0.0 launch — `register()` and the raw-Commander `program` handle were
|
|
19
|
+
* removed; "one command surface", §8).
|
|
20
|
+
*
|
|
21
|
+
* The two-field shape (commands[] for metadata; commandSpecs for the typed
|
|
22
|
+
* command surface) keeps `--help` discovery cheap (no per-tool Commander
|
|
23
|
+
* invocation required to enumerate available commands) while the host owns
|
|
24
|
+
* the full option-parsing / output / error pipeline for every command.
|
|
25
|
+
*/
|
|
26
|
+
import { ToolError, type ToolErrorOptions } from '../lib/errors.js';
|
|
27
|
+
import type { CapabilityRegistrar, ToolConfigContribution } from './capability.js';
|
|
28
|
+
import type { CommandSpec } from './command-spec.js';
|
|
29
|
+
import type { ToolShortId } from './ids.js';
|
|
30
|
+
import type { FingerprintStrategy } from '../baseline/fingerprint-strategy.js';
|
|
31
|
+
import type { Logger } from '../lib/logger.js';
|
|
32
|
+
import type { RunTimer } from '../lib/run-timer.js';
|
|
33
|
+
import type { ScopeContribution, ToolScope } from '../lib/scope-types.js';
|
|
34
|
+
import type { PluginLayout } from '../plugins/types.js';
|
|
35
|
+
import type { Signal } from '../types/signal.js';
|
|
36
|
+
/**
|
|
37
|
+
* The current version of the `Tool` plugin contract.
|
|
38
|
+
*
|
|
39
|
+
* Tool authors may optionally set `contractVersion: TOOL_CONTRACT_VERSION`
|
|
40
|
+
* (or a string matching a future version) on their exported `Tool` object.
|
|
41
|
+
*
|
|
42
|
+
* ## Versioning Policy (ADR-0046)
|
|
43
|
+
*
|
|
44
|
+
* - `TOOL_CONTRACT_VERSION` is bumped **only** when the shape or documented
|
|
45
|
+
* semantics of the `Tool` interface (or the `ToolExtensionPoints` contract)
|
|
46
|
+
* actually change in a way that could affect tool authors.
|
|
47
|
+
* - When a contract change ships, the value is set to the major.minor of the
|
|
48
|
+
* CLI release in which the change is first released (e.g. a breaking contract
|
|
49
|
+
* change released as part of CLI v1.2.0 results in
|
|
50
|
+
* `TOOL_CONTRACT_VERSION = '1.2'`).
|
|
51
|
+
* - Releases that do not touch the Tool contract leave the constant at its
|
|
52
|
+
* previous value (it will frequently lag the CLI version — this is
|
|
53
|
+
* intentional).
|
|
54
|
+
* - The primary evolution mechanism remains `extensionPoints` (see below and
|
|
55
|
+
* the `Tool` interface JSDoc). `contractVersion` is a marker only.
|
|
56
|
+
*
|
|
57
|
+
* The host can use the declared value for diagnostics, logging
|
|
58
|
+
* ("tool X was written against contract vY"), future compatibility warnings,
|
|
59
|
+
* or ratcheting in the plugin loader / compatibility gate.
|
|
60
|
+
*
|
|
61
|
+
* See ADR-0046 for the full policy, alternatives considered, and enforcement.
|
|
62
|
+
*/
|
|
63
|
+
export declare const TOOL_CONTRACT_VERSION = "1.0.0";
|
|
64
|
+
/** Static descriptor for a tool plugin: id, semver, and one-line description. */
|
|
65
|
+
export interface ToolMetadata {
|
|
66
|
+
/**
|
|
67
|
+
* Stable identity (real UUID). Matches the `id` field used for Checks'
|
|
68
|
+
* stable UUID (per ADR-0048 and governing spec). Used for durable DB
|
|
69
|
+
* scoping, provenance, agent-catalog, future ratchets, etc.
|
|
70
|
+
*/
|
|
71
|
+
readonly id: string;
|
|
72
|
+
/**
|
|
73
|
+
* Human-facing name / current key (what was previously stored in the old
|
|
74
|
+
* `id` field). Used for UX, config namespaces, CLI short forms, on-disk
|
|
75
|
+
* hints, and current DB `tool` column values.
|
|
76
|
+
*/
|
|
77
|
+
readonly name: string;
|
|
78
|
+
readonly version: string;
|
|
79
|
+
readonly description: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Identity of a command a tool contributes — used for --help, plugin
|
|
83
|
+
* listings, and conflict detection across tools. The actual handler is
|
|
84
|
+
* wired up by the tool's `commandSpecs` (mounted by the host).
|
|
85
|
+
*/
|
|
86
|
+
export interface ToolCommandDescriptor {
|
|
87
|
+
/** CLI subcommand name — 'fit', 'sim', 'fit-list', etc. */
|
|
88
|
+
readonly name: string;
|
|
89
|
+
readonly description: string;
|
|
90
|
+
readonly aliases?: readonly string[];
|
|
91
|
+
/**
|
|
92
|
+
* Whether this command requires a project context (RunScope with datastore etc.).
|
|
93
|
+
* Mirrors CommandSpec.scope. 'project' (default for most) vs 'none' (e.g. configure).
|
|
94
|
+
* Populated from the tool's CommandSpec so the declared scope drives host behavior
|
|
95
|
+
* (pre-action guards, etc.) instead of a hardcoded name list.
|
|
96
|
+
*/
|
|
97
|
+
readonly scope?: 'project' | 'none';
|
|
98
|
+
}
|
|
99
|
+
/** Generic stored-session shape accepted by tool replay hooks.
|
|
100
|
+
*
|
|
101
|
+
* This mirrors `@opensip-cli/contracts` `StoredSession` structurally without
|
|
102
|
+
* importing contracts into core. The CLI passes hydrated session-store rows;
|
|
103
|
+
* tools narrow their opaque payloads inside their own replay builders.
|
|
104
|
+
*/
|
|
105
|
+
export interface ToolSessionRecord {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
readonly tool: ToolShortId;
|
|
108
|
+
readonly startedAt: string;
|
|
109
|
+
readonly completedAt: string;
|
|
110
|
+
readonly cwd: string;
|
|
111
|
+
readonly recipe?: string;
|
|
112
|
+
readonly score: number;
|
|
113
|
+
readonly passed: boolean;
|
|
114
|
+
readonly durationMs: number;
|
|
115
|
+
readonly payload?: unknown;
|
|
116
|
+
}
|
|
117
|
+
/** Optional tool contribution for host-owned `sessions show` replay. */
|
|
118
|
+
export interface ToolSessionReplayContribution {
|
|
119
|
+
readonly tool: ToolShortId;
|
|
120
|
+
readonly replaySession: (stored: ToolSessionRecord) => unknown;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The generic-session contribution a tool returns from its command handler or
|
|
124
|
+
* live renderer (host-owned-run-timing §6.2).
|
|
125
|
+
*
|
|
126
|
+
* Tools provide only verdict + payload + provenance. The host run-lifecycle
|
|
127
|
+
* plane stamps `startedAt` / `completedAt` / `durationMs` (from the shared
|
|
128
|
+
* `RunLifecycle`), generates the stable `id`, and performs the actual
|
|
129
|
+
* `SessionRepo.save` *after* the tool returns. Tools never capture run timing
|
|
130
|
+
* and never call a generic-session writer themselves.
|
|
131
|
+
*
|
|
132
|
+
* Persistence is best-effort: when no datastore is available (non-project
|
|
133
|
+
* commands, or tests without a scope) the host writes nothing observable.
|
|
134
|
+
* Tools must never assume a row was written.
|
|
135
|
+
*/
|
|
136
|
+
export interface ToolSessionContribution {
|
|
137
|
+
readonly tool: ToolShortId;
|
|
138
|
+
readonly cwd: string;
|
|
139
|
+
readonly recipe?: string;
|
|
140
|
+
readonly score: number;
|
|
141
|
+
readonly passed: boolean;
|
|
142
|
+
/** Tool-owned opaque payload (same contract as StoredSession.payload). */
|
|
143
|
+
readonly payload?: unknown;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Legacy alias for {@link ToolSessionContribution} — the input shape the
|
|
147
|
+
* transitional `runSession.record(...)` seam accepts. Removed once the
|
|
148
|
+
* record seam is deleted (host-owned-run-timing Phase 3); new code returns a
|
|
149
|
+
* {@link ToolRunCompletion} instead of calling `record`.
|
|
150
|
+
*/
|
|
151
|
+
export type ToolRunSessionInput = ToolSessionContribution;
|
|
152
|
+
/**
|
|
153
|
+
* What a tool command handler or live renderer returns to the host so the
|
|
154
|
+
* host can complete the run lifecycle and persist the generic session row
|
|
155
|
+
* (host-owned-run-timing §6.2).
|
|
156
|
+
*
|
|
157
|
+
* - `result` / `envelope` are the tool's domain outputs (the same shapes the
|
|
158
|
+
* handler already produced) — optional so a live renderer that only persists
|
|
159
|
+
* can return just `session`.
|
|
160
|
+
* - `session` is the generic-session contribution the host persists.
|
|
161
|
+
*
|
|
162
|
+
* The host receives this and owns the rest; the tool supplies no lifecycle
|
|
163
|
+
* timing and performs no generic-session write.
|
|
164
|
+
*/
|
|
165
|
+
export interface ToolRunCompletion {
|
|
166
|
+
readonly result?: unknown;
|
|
167
|
+
readonly envelope?: unknown;
|
|
168
|
+
readonly session?: ToolSessionContribution;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* The host-recorded session, returned by the host run plane after it persists a
|
|
172
|
+
* {@link ToolSessionContribution}. Carries the id the host assigned and the
|
|
173
|
+
* timing it stamped from the run lifecycle. This is a HOST-internal return shape
|
|
174
|
+
* (the run plane → host), not a tool-facing seam.
|
|
175
|
+
*/
|
|
176
|
+
export interface RecordedToolRunSession {
|
|
177
|
+
readonly id: string;
|
|
178
|
+
readonly tool: ToolShortId;
|
|
179
|
+
readonly startedAt: string;
|
|
180
|
+
readonly completedAt: string;
|
|
181
|
+
readonly durationMs: number;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The host-provided run seam on `ToolCliContext` (host-owned-run-timing §6.5).
|
|
185
|
+
*
|
|
186
|
+
* `timing` is the host run lifecycle for this invocation — READ-ONLY lifecycle
|
|
187
|
+
* inspection for display (e.g. live elapsed in a summary). The launch surface
|
|
188
|
+
* intentionally exposes NO generic-session writer: tools return a
|
|
189
|
+
* {@link ToolSessionContribution} (inside a {@link ToolRunCompletion}) from
|
|
190
|
+
* their handler / live renderer and the host persists it after they resolve.
|
|
191
|
+
*/
|
|
192
|
+
export interface ToolRunSessions {
|
|
193
|
+
readonly timing: RunTimer;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Context object passed as the second argument to a `LiveViewRenderer`.
|
|
197
|
+
* Carries the host run seam so a live renderer reads the same lifecycle
|
|
198
|
+
* (timer) the host will snapshot on completion. In the launch model the
|
|
199
|
+
* renderer returns its {@link ToolRunCompletion} to the host rather than
|
|
200
|
+
* calling `record` itself.
|
|
201
|
+
*/
|
|
202
|
+
export interface LiveViewContext {
|
|
203
|
+
readonly runSession: ToolRunSessions;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Renderer signature for a tool-contributed live view. The CLI looks up
|
|
207
|
+
* the registered renderer by key when a tool calls
|
|
208
|
+
* `ToolCliContext.renderLive(key, args)` and invokes it with the tool's
|
|
209
|
+
* args payload.
|
|
210
|
+
*
|
|
211
|
+
* Renderers are tool-specific. They typically wrap an Ink `render(...)`
|
|
212
|
+
* call against a stateful component (FitView, GraphView) and resolve
|
|
213
|
+
* once the underlying Ink app exits.
|
|
214
|
+
*
|
|
215
|
+
* The `args` parameter is `unknown` at the contract layer because each
|
|
216
|
+
* tool defines its own args shape; tools narrow the type inside their
|
|
217
|
+
* own renderer body via a runtime cast.
|
|
218
|
+
*
|
|
219
|
+
* In the host-owned run-lifecycle model, the second `context` argument carries
|
|
220
|
+
* the host run seam (the {@link LiveViewContext}) and is supplied by the host
|
|
221
|
+
* for every live tool command. A live renderer must NOT call a generic-session
|
|
222
|
+
* writer itself; instead it returns a {@link ToolRunCompletion} (or `void`)
|
|
223
|
+
* once the underlying Ink app exits, and the host completes the lifecycle and
|
|
224
|
+
* persists the session contribution after `await renderLive(...)`. The
|
|
225
|
+
* parameter stays optional at the type level during the migration window
|
|
226
|
+
* (Phase 2 makes it effectively required for live tool commands).
|
|
227
|
+
*/
|
|
228
|
+
export type LiveViewRenderer = (args: unknown, context?: LiveViewContext) => Promise<ToolRunCompletion | void>;
|
|
229
|
+
/**
|
|
230
|
+
* Thrown by `ToolCliContext.renderLive(key, args)` when no renderer has
|
|
231
|
+
* been registered for `key`. A typed throw is preferable to silently
|
|
232
|
+
* falling back to a static render — the latter masked bugs where a tool
|
|
233
|
+
* mistyped its view key.
|
|
234
|
+
*/
|
|
235
|
+
export declare class UnknownLiveViewError extends ToolError {
|
|
236
|
+
readonly viewKey: string;
|
|
237
|
+
constructor(viewKey: string, options?: ToolErrorOptions);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Result of the host baseline/ratchet compare seam (ADR-0036) — three full-object
|
|
241
|
+
* buckets + the gate decision. Core declares this thin shape for the
|
|
242
|
+
* {@link ToolCliContext.compareBaseline} return so `core` need not import
|
|
243
|
+
* `@opensip-cli/output` (which owns the authoritative `GateCompareResult` used
|
|
244
|
+
* by `diffBaseline`). The two are kept structurally in sync by a dedicated test
|
|
245
|
+
* (`core ↔ output GateCompareResult must not diverge`).
|
|
246
|
+
*/
|
|
247
|
+
export interface GateCompareResult {
|
|
248
|
+
/** Findings present now but not in the baseline (current ∖ baseline). */
|
|
249
|
+
readonly added: readonly Signal[];
|
|
250
|
+
/** Findings present in the baseline but not now (baseline ∖ current). */
|
|
251
|
+
readonly resolved: readonly Signal[];
|
|
252
|
+
/** Findings present in both (current ∩ baseline). */
|
|
253
|
+
readonly unchanged: readonly Signal[];
|
|
254
|
+
/** True iff `added` is non-empty — the gate decision. */
|
|
255
|
+
readonly degraded: boolean;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Outcome of the root's post-run signal delivery
|
|
259
|
+
* ({@link ToolCliContext.deliverSignals}). Delivery stays best-effort and
|
|
260
|
+
* non-blocking (ADR-0008) — this result exists so a caller (or a test) can
|
|
261
|
+
* SURFACE what happened instead of the user silently assuming their signals
|
|
262
|
+
* shipped. The root already prints the user-facing skip/failure notices; tools
|
|
263
|
+
* may ignore the result entirely.
|
|
264
|
+
*/
|
|
265
|
+
export interface SignalDeliveryResult {
|
|
266
|
+
/** Signals the cloud sink acknowledged (0 for the keyless/no-op majority). */
|
|
267
|
+
readonly cloudAccepted: number;
|
|
268
|
+
/**
|
|
269
|
+
* Why an ACTIVE cloud sink accepted nothing, when knowable: `'unentitled'`
|
|
270
|
+
* (the entitlement check said no) or `'error'` (the emit faulted). Omitted on
|
|
271
|
+
* success and for the no-op sink (user opted out / no key — silence correct).
|
|
272
|
+
*/
|
|
273
|
+
readonly cloudSkippedReason?: 'unentitled' | 'error';
|
|
274
|
+
/** Whether a `--report-to` upload was attempted and succeeded. */
|
|
275
|
+
readonly reportSuccess?: boolean;
|
|
276
|
+
/** The `--report-to` target URL, when one was requested. */
|
|
277
|
+
readonly reportUrl?: string;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Wire alias for run envelopes passed across the core ↔ cli seam.
|
|
281
|
+
*
|
|
282
|
+
* Typed `unknown` here because core must not depend on @opensip-cli/contracts
|
|
283
|
+
* (layering). The composition root (cli) narrows it to `SignalEnvelope`.
|
|
284
|
+
* This is the documented cost of strict kernel layering; shape-sync tests
|
|
285
|
+
* and the explicit `Wire*` aliases are the hygiene.
|
|
286
|
+
*
|
|
287
|
+
* (GA Lows cleanup, 2026-06: alias + usage added as part of resolving the
|
|
288
|
+
* "heavy unknown + casts" item. See roadmap item 5.)
|
|
289
|
+
*/
|
|
290
|
+
type WireSignalEnvelope = unknown;
|
|
291
|
+
/**
|
|
292
|
+
* Context the host hands to each command handler (and the tool's optional
|
|
293
|
+
* lifecycle hooks): the shared CLI behaviour a handler calls back into — Ink
|
|
294
|
+
* rendering, machine-output emit seams, report auto-open, structured logging,
|
|
295
|
+
* per-run scope — without depending on the CLI package directly.
|
|
296
|
+
*
|
|
297
|
+
* 1.0.0 launch: this context carries NO Commander `program`. Tools declare
|
|
298
|
+
* `commandSpecs` and the host mounts them (`mountCommandSpec`); a handler has no
|
|
299
|
+
* raw-Commander handle to reach, so the "one command surface" invariant (§8) is
|
|
300
|
+
* structural, not merely guarded. The host owns the program internally and passes
|
|
301
|
+
* it to its own mount step (`mountAllToolCommands(registry, program, ctx)`).
|
|
302
|
+
*/
|
|
303
|
+
export interface ToolCliContext {
|
|
304
|
+
/**
|
|
305
|
+
* Per-run resources (logger, parseCache, registries, datastore,
|
|
306
|
+
* recipeUnitConfig, projectContext). Constructed once per CLI
|
|
307
|
+
* invocation by the bootstrap. Tools read every per-run resource
|
|
308
|
+
* via `cli.scope.foo` — the previously-exported `defaultToolRegistry`
|
|
309
|
+
* / `defaultLanguageRegistry` singletons are gone, and the Phase 5
|
|
310
|
+
* `cli.project` / `cli.datastore` back-compat alias accessors were
|
|
311
|
+
* retired in audit-round-3 Finding K once no tool referenced them
|
|
312
|
+
* directly. Read `cli.scope.projectContext` and `cli.scope.datastore()`
|
|
313
|
+
* instead.
|
|
314
|
+
*
|
|
315
|
+
* Typed as the Tool-facing `ToolScope` view (not the concrete
|
|
316
|
+
* `RunScope`): everything tools read via `cli.scope.*`, minus the
|
|
317
|
+
* `tools` registry tools never touch. This is what keeps the `Tool`
|
|
318
|
+
* contract free of any `RunScope` reference (audit 2026-05-29, M4).
|
|
319
|
+
*
|
|
320
|
+
* Host-owned planes live here (baselines, toolState per ADR-0042, and now
|
|
321
|
+
* the combined governance/entitlements/audit plane via the `hostPlanes`
|
|
322
|
+
* evolution bag). See the plan and spec for H1-H3.
|
|
323
|
+
*/
|
|
324
|
+
readonly scope: ToolScope;
|
|
325
|
+
/**
|
|
326
|
+
* Host-owned run lifecycle seam (host-owned-run-timing).
|
|
327
|
+
*
|
|
328
|
+
* `timing` is the single `RunLifecycle` the CLI host creates inside the
|
|
329
|
+
* command action (after `RunScope` entry, before any tool handler or live
|
|
330
|
+
* view). It is the source of truth for `StoredSession.startedAt` /
|
|
331
|
+
* `completedAt` / `durationMs`; tools may read it for display-only elapsed.
|
|
332
|
+
*
|
|
333
|
+
* `record(...)` is TRANSITIONAL and slated for removal (Phases 3/6). The
|
|
334
|
+
* launch model is: return a `ToolSessionContribution` (inside a
|
|
335
|
+
* `ToolRunCompletion`) from your command handler / live renderer and let the
|
|
336
|
+
* host complete the lifecycle and persist after you return.
|
|
337
|
+
*
|
|
338
|
+
* Architectural rule: tools must not capture `Date` / `performance` for the
|
|
339
|
+
* generic session timing fields, must not import or call `SessionRepo`
|
|
340
|
+
* directly for the generic columns, and must not build new code against
|
|
341
|
+
* `record(...)`.
|
|
342
|
+
*/
|
|
343
|
+
readonly runSession: ToolRunSessions;
|
|
344
|
+
/** Render an Ink result (CommandResult shape from @opensip-cli/contracts). */
|
|
345
|
+
readonly render: (result: unknown) => Promise<void>;
|
|
346
|
+
/**
|
|
347
|
+
* Register a renderer for a live, stateful view keyed by `key`. Tools
|
|
348
|
+
* call this (lazily, from a setup hook on first live render) to contribute
|
|
349
|
+
* their own Ink view (spinner → results transition); the CLI then dispatches
|
|
350
|
+
* to the registered renderer when `renderLive(key, args)` is invoked.
|
|
351
|
+
*
|
|
352
|
+
* Registration is first-writer-wins, matching the policy used by
|
|
353
|
+
* `ToolRegistry.register`. A duplicate key triggers a structured
|
|
354
|
+
* `cli.live_view.duplicate` warning via the shared logger and the
|
|
355
|
+
* second call is silently ignored.
|
|
356
|
+
*/
|
|
357
|
+
readonly registerLiveView: (key: string, renderer: LiveViewRenderer) => void;
|
|
358
|
+
/**
|
|
359
|
+
* Render the live view registered under `key`, passing `args` through
|
|
360
|
+
* to the registered renderer. Resolves once the underlying Ink app exits,
|
|
361
|
+
* with the renderer's {@link ToolRunCompletion} (or `void`). The host
|
|
362
|
+
* completes the run lifecycle and persists the returned `session`
|
|
363
|
+
* contribution after the renderer resolves — the renderer must NOT call a
|
|
364
|
+
* generic-session writer itself. Throws `UnknownLiveViewError` if no
|
|
365
|
+
* renderer has been registered for `key` (rather than silently falling back
|
|
366
|
+
* to a static render — the latter would mask bugs where a tool mistypes its
|
|
367
|
+
* view key).
|
|
368
|
+
*
|
|
369
|
+
* `key` is a string instead of a typed enum so new tools can
|
|
370
|
+
* contribute additional live views without touching the core type. The
|
|
371
|
+
* host supplies the `LiveViewContext` for live tool commands; tools should
|
|
372
|
+
* not pass it themselves.
|
|
373
|
+
*/
|
|
374
|
+
readonly renderLive: (key: string, args: unknown, liveContext?: LiveViewContext) => Promise<ToolRunCompletion | void>;
|
|
375
|
+
/**
|
|
376
|
+
* Open the HTML report in the user's browser when the run
|
|
377
|
+
* conditions allow it (TTY, not JSON-mode, opt-in). Tools call this
|
|
378
|
+
* after a run to honor the user's --open flag.
|
|
379
|
+
*/
|
|
380
|
+
readonly maybeOpenReport: (opts: {
|
|
381
|
+
openRequested: boolean;
|
|
382
|
+
jsonOutput: boolean;
|
|
383
|
+
}) => Promise<void>;
|
|
384
|
+
/** Shared structured logger. */
|
|
385
|
+
readonly logger: Logger;
|
|
386
|
+
/**
|
|
387
|
+
* Process exit-code setter — tools call this instead of mutating
|
|
388
|
+
* `process.exitCode` directly so the CLI controls the final exit.
|
|
389
|
+
*/
|
|
390
|
+
readonly setExitCode: (code: number) => void;
|
|
391
|
+
/**
|
|
392
|
+
* Read the exit code set so far this run (`undefined` if none set yet). The
|
|
393
|
+
* host always provides it; it is optional only so the many inline test
|
|
394
|
+
* `ToolCliContext` stubs need not stub it. Used by gate COMPARE modes, which
|
|
395
|
+
* set their baseline-diff exit upstream and must re-affirm it when the host's
|
|
396
|
+
* `deliverSignals` would otherwise derive a findings exit from the run verdict
|
|
397
|
+
* (ADR-0035).
|
|
398
|
+
*/
|
|
399
|
+
readonly getExitCode?: () => number | undefined;
|
|
400
|
+
/**
|
|
401
|
+
* Emit a structured JSON value to the CLI's stdout. Centralises the
|
|
402
|
+
* `process.stdout.write(JSON.stringify(value, null, 2) + '\n')` call
|
|
403
|
+
* that every tool's `--json` mode would otherwise duplicate. The CLI
|
|
404
|
+
* owns the IO seam; tools call `emitJson` and the CLI decides how the
|
|
405
|
+
* value reaches the terminal.
|
|
406
|
+
*
|
|
407
|
+
* This is the **general-purpose JSON seam**, distinct from `emitEnvelope`
|
|
408
|
+
* (below). Use it for `--json` output that is NOT a run-signal envelope:
|
|
409
|
+
* auxiliary/list subcommands (`fit-list`, `fit-recipes`, `graph-lookup`,
|
|
410
|
+
* `graph-symbol-index`), the `graph --workspace --json` report document,
|
|
411
|
+
* and bare error objects (`{ error }`). The main analyze commands' run
|
|
412
|
+
* output goes through `emitEnvelope` instead. Both are current, sanctioned
|
|
413
|
+
* stdout seams — see the `no-direct-stdout-in-tool-engine` check, which
|
|
414
|
+
* permits exactly `render` / `emitJson` / `emitEnvelope` / `deliverSignals`
|
|
415
|
+
* / `writeSarif`.
|
|
416
|
+
*/
|
|
417
|
+
readonly emitJson: (value: unknown) => void;
|
|
418
|
+
/**
|
|
419
|
+
* Emit a tool **run-signal envelope** as machine-output (ADR-0011). The
|
|
420
|
+
* CLI composition root formats the envelope through the single shared
|
|
421
|
+
* `formatSignalJson` formatter and writes it to stdout — so the `--json`
|
|
422
|
+
* wire contract for a run lives in `@opensip-cli/output`, not
|
|
423
|
+
* re-stringified per tool.
|
|
424
|
+
*
|
|
425
|
+
* This is the specialised seam for the **main analyze commands' run output**
|
|
426
|
+
* (`fit`, `graph`, `sim`): they build a `SignalEnvelope` and call
|
|
427
|
+
* `emitEnvelope`, where the older bespoke-JSON path used `emitJson(result)`
|
|
428
|
+
* (the ADR-0011 Phase 4–6 migration, now complete). `emitJson` remains for
|
|
429
|
+
* everything that is not a run envelope (see above) — the two seams are
|
|
430
|
+
* complementary, not transitional.
|
|
431
|
+
*
|
|
432
|
+
* The value is the `SignalEnvelope` from `@opensip-cli/contracts`; it is
|
|
433
|
+
* typed `unknown` here for the same reason `render`/`emitJson` are — the
|
|
434
|
+
* `Tool` contract in core must not name the contracts-layer payload type
|
|
435
|
+
* (that edge would invert the layer graph). The composition root narrows
|
|
436
|
+
* it.
|
|
437
|
+
*
|
|
438
|
+
* Hygiene note (GA Low): this `unknown` + cast pattern is the cost of
|
|
439
|
+
* strict layering (core imports nothing workspace). See the shape-sync
|
|
440
|
+
* tests and `WireSignalEnvelope` alias below for the invariant.
|
|
441
|
+
*/
|
|
442
|
+
readonly emitEnvelope: (envelope: WireSignalEnvelope) => void;
|
|
443
|
+
/**
|
|
444
|
+
* Emit a **structured error** as machine-output (launch, §5.5). The
|
|
445
|
+
* host wraps `{ message, exitCode, suggestion? }` in a `status:'error'`
|
|
446
|
+
* `CommandOutcome` (`.errors`) through the single `renderOutcome` seam, and
|
|
447
|
+
* threads `exitCode` to `setExitCode` so the process exit and the reported
|
|
448
|
+
* outcome agree.
|
|
449
|
+
*
|
|
450
|
+
* This RETIRES the bare `emitJson({ error })` shape: a `--json` run that fails
|
|
451
|
+
* before it can build an envelope (e.g. a config error) calls `emitError`
|
|
452
|
+
* instead, so machine consumers read one outcome schema for success AND
|
|
453
|
+
* failure. The `one-outcome-shape` guardrail forbids the bare shape.
|
|
454
|
+
*/
|
|
455
|
+
readonly emitError: (detail: {
|
|
456
|
+
readonly message: string;
|
|
457
|
+
readonly exitCode: number;
|
|
458
|
+
readonly suggestion?: string;
|
|
459
|
+
/**
|
|
460
|
+
* Optional machine-readable error category (e.g. `'not-found'`,
|
|
461
|
+
* `'decode-error'`). The host surfaces it as the structured
|
|
462
|
+
* `ErrorDetail.code` so machine consumers can branch on the failure kind
|
|
463
|
+
* without parsing `message`.
|
|
464
|
+
*/
|
|
465
|
+
readonly code?: string;
|
|
466
|
+
}) => void;
|
|
467
|
+
/**
|
|
468
|
+
* Emit a **raw, unwrapped** value as machine-output for a command that
|
|
469
|
+
* declares `output:'raw-stream'` (north-star §5.5). Unlike `emitJson`/
|
|
470
|
+
* `emitEnvelope`/`emitError` — which wrap the payload in the outer
|
|
471
|
+
* `CommandOutcome` currency — this writes the bare value as a single compact
|
|
472
|
+
* JSON line, the smallest possible response for agents (e.g. `sessions show
|
|
473
|
+
* --raw`: session metadata + envelope + hints, no wrapper).
|
|
474
|
+
*
|
|
475
|
+
* It is a deliberate, declared opt-out of the one-outcome shape, NOT a bypass:
|
|
476
|
+
* the single sanctioned write still lives in the host's one stdout-JSON seam
|
|
477
|
+
* (`renderRaw` in render-outcome), so no command body hand-rolls
|
|
478
|
+
* `process.stdout.write(JSON.stringify(...))`. A command without
|
|
479
|
+
* `output:'raw-stream'` should use `emitJson` instead.
|
|
480
|
+
*/
|
|
481
|
+
readonly emitRaw: (value: unknown) => void;
|
|
482
|
+
/**
|
|
483
|
+
* Deliver a tool-run **signal envelope** to the effectful sinks the
|
|
484
|
+
* composition root owns (ADR-0011 / ADR-0008): best-effort cloud sync via
|
|
485
|
+
* the run's `scope.signalSink`, and — when `--report-to` is set — a SARIF
|
|
486
|
+
* upload (which owns exit code 4). The tool builds the envelope and calls
|
|
487
|
+
* this **once per run** after rendering / emitting; the root maps it to
|
|
488
|
+
* `SignalBatch` (cloud) and `formatSignalSarif` (report-to). Awaitable so
|
|
489
|
+
* egress completes before the short-lived CLI process exits.
|
|
490
|
+
*
|
|
491
|
+
* This replaces the per-tool `emitRunSignals` / `reportToCloud` calls the
|
|
492
|
+
* engines make today — moving all egress to the root lets the engines drop
|
|
493
|
+
* their `@opensip-cli/output` dependency (Phases 4–6). Best-effort: cloud
|
|
494
|
+
* failures never throw and never affect the exit code; only a `--report-to`
|
|
495
|
+
* failure on an otherwise-passing run sets exit 4. Resolves to a
|
|
496
|
+
* {@link SignalDeliveryResult} stating what actually shipped (the root also
|
|
497
|
+
* prints the user-facing skip/failure notices); callers may ignore it.
|
|
498
|
+
*
|
|
499
|
+
* `envelope` is the `SignalEnvelope` from `@opensip-cli/contracts`, typed
|
|
500
|
+
* `unknown` here for the same layer reason as `render`/`emitEnvelope`.
|
|
501
|
+
*/
|
|
502
|
+
readonly deliverSignals: (envelope: WireSignalEnvelope, opts: {
|
|
503
|
+
readonly cwd: string;
|
|
504
|
+
readonly reportTo?: string;
|
|
505
|
+
readonly apiKey?: string;
|
|
506
|
+
readonly runFailed?: boolean;
|
|
507
|
+
}) => Promise<SignalDeliveryResult>;
|
|
508
|
+
/**
|
|
509
|
+
* Write a tool-run **signal envelope** to a SARIF v2.1.0 file (ADR-0011).
|
|
510
|
+
* The composition root formats the envelope through the single shared
|
|
511
|
+
* `formatSignalSarif` formatter and writes the bytes to `path` (creating
|
|
512
|
+
* parent directories as needed). This is the root-owned SARIF-**file** sink
|
|
513
|
+
* — distinct from `--report-to` (a network sink) and the cloud sync — so a
|
|
514
|
+
* tool that exports SARIF to a file (e.g. `graph sarif-export`, the
|
|
515
|
+
* cross-repo `EngineSubprocessPort.runSarifExport` contract) does it through
|
|
516
|
+
* the root instead of importing `@opensip-cli/output` itself. Awaitable so
|
|
517
|
+
* the write completes before the short-lived CLI process exits.
|
|
518
|
+
*
|
|
519
|
+
* `envelope` is the `SignalEnvelope` from `@opensip-cli/contracts`, typed
|
|
520
|
+
* `unknown` here for the same layer reason as `render`/`emitEnvelope`/
|
|
521
|
+
* `deliverSignals`.
|
|
522
|
+
*/
|
|
523
|
+
readonly writeSarif: (envelope: WireSignalEnvelope, path: string) => Promise<void>;
|
|
524
|
+
/**
|
|
525
|
+
* Host baseline/ratchet plane seams (ADR-0036). The host owns persistence
|
|
526
|
+
* (`BaselineRepo`), the diff, and exit derivation; a tool inherits a CI ratchet
|
|
527
|
+
* by emitting fingerprint-stamped signals. The seams are **read-only** of
|
|
528
|
+
* `signal.fingerprint` — the tool stamps its envelope's signals
|
|
529
|
+
* (`stampFingerprints`) at envelope-construction time; the plane NEVER
|
|
530
|
+
* re-fingerprints. `tool` scopes every operation; `envelope` is the
|
|
531
|
+
* `SignalEnvelope` typed `unknown` here for the same layer reason as
|
|
532
|
+
* `writeSarif`/`deliverSignals`.
|
|
533
|
+
*/
|
|
534
|
+
readonly saveBaseline: (tool: string, envelope: WireSignalEnvelope) => Promise<void>;
|
|
535
|
+
/**
|
|
536
|
+
* Compare the current (stamped) envelope against this tool's saved baseline.
|
|
537
|
+
* Throws a `ConfigurationError` (→ exit 2) when no baseline exists. The host
|
|
538
|
+
* derives the gate exit from `result.degraded` via the `deliverSignals`
|
|
539
|
+
* runFailed override — no tool calls `setExitCode` for the gate path (ADR-0035).
|
|
540
|
+
*/
|
|
541
|
+
readonly compareBaseline: (tool: string, envelope: WireSignalEnvelope) => Promise<GateCompareResult>;
|
|
542
|
+
/**
|
|
543
|
+
* Export this tool's baseline to a SARIF file by reconstructing a synthetic
|
|
544
|
+
* envelope from the stored per-fingerprint payloads (no stored envelope to
|
|
545
|
+
* reload). Throws when no baseline exists.
|
|
546
|
+
*/
|
|
547
|
+
readonly exportBaselineSarif: (tool: string, path: string) => Promise<void>;
|
|
548
|
+
/**
|
|
549
|
+
* Export this tool's baseline as the git-trackable fingerprint JSON
|
|
550
|
+
* (`{version,tool,capturedAt,fingerprints[]}`). Throws when no baseline exists.
|
|
551
|
+
*/
|
|
552
|
+
readonly exportBaselineFingerprints: (tool: string, path: string) => Promise<void>;
|
|
553
|
+
/**
|
|
554
|
+
* Host-owned keyed tool state (ADR-0042) — durable, per-tool, opaque-JSON
|
|
555
|
+
* persistence over the generic `tool_state` table, the third-party parity
|
|
556
|
+
* mechanism beside sessions + baselines. ONE grouped member (not four flat
|
|
557
|
+
* seams — the interface-segregation lesson from the baseline plane). Rules:
|
|
558
|
+
*
|
|
559
|
+
* - `tool` scopes every operation; a tool never sees another's rows.
|
|
560
|
+
* - Payloads are opaque JSON, capped at 256 KiB per payload; an oversized
|
|
561
|
+
* `put` throws a `ValidationError` (error, never evict).
|
|
562
|
+
* - Durable: unlike baselines (drop-and-recapture), a release never drops
|
|
563
|
+
* these rows. `tools data purge <tool-id>` clears them on request.
|
|
564
|
+
* - Requires the entered project scope (the datastore is per-project);
|
|
565
|
+
* calls outside one reject with the host's datastore-unavailable error.
|
|
566
|
+
*/
|
|
567
|
+
readonly toolState: {
|
|
568
|
+
readonly get: (tool: string, key: string) => Promise<unknown>;
|
|
569
|
+
readonly put: (tool: string, key: string, payload: unknown) => Promise<void>;
|
|
570
|
+
readonly delete: (tool: string, key: string) => Promise<void>;
|
|
571
|
+
readonly list: (tool: string) => Promise<readonly string[]>;
|
|
572
|
+
};
|
|
573
|
+
/**
|
|
574
|
+
* Host-owned evolution bag for additional durable/governance planes.
|
|
575
|
+
*
|
|
576
|
+
* This is the combined Host-Owned Governance, Entitlements, and Audit Plane
|
|
577
|
+
* (H1: Extension/Community Governance, H2: Per-Tool Audit/Provenance/Decision Records,
|
|
578
|
+
* H3: Entitlements/Licensing/Paid-Extension State).
|
|
579
|
+
*
|
|
580
|
+
* See:
|
|
581
|
+
* - the "Host-Owned Governance, Entitlements & Audit Plane" spec + plan
|
|
582
|
+
* (local-only working docs under docs/plans/, by that title)
|
|
583
|
+
* - ADR-0042 (toolState baseline this reuses)
|
|
584
|
+
*
|
|
585
|
+
* Design: typed seams here (host provides the impl), opaque/namespaced storage under the
|
|
586
|
+
* existing toolState seam (and the single host-owned `tool_state` table). Tools never
|
|
587
|
+
* touch raw datastore for these concerns. The bag prevents interface bloat on ToolCliContext
|
|
588
|
+
* (symmetric to ToolExtensionPoints on the Tool side).
|
|
589
|
+
*
|
|
590
|
+
* All members are optional so this change is purely additive for GA-era code and stubs.
|
|
591
|
+
*/
|
|
592
|
+
readonly hostPlanes?: {
|
|
593
|
+
governance?: HostGovernance;
|
|
594
|
+
audit?: HostAudit;
|
|
595
|
+
entitlements?: HostEntitlements;
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Stable (but minimal) interfaces for the host-provided governance / audit / entitlements planes.
|
|
600
|
+
* These are defined in core so that both the host (CLI) and consumers (Cloud, future community tools)
|
|
601
|
+
* have a single source of truth.
|
|
602
|
+
*
|
|
603
|
+
* Cloud is the primary consumer. Third-party / OSS tool authors may:
|
|
604
|
+
* - ignore the bag entirely, or
|
|
605
|
+
* - use the existing `toolState` seam directly for custom records, or
|
|
606
|
+
* - supply compatible objects (the host will prefer a supplied implementation when present).
|
|
607
|
+
*
|
|
608
|
+
* See the governing "Host-Planes / Scope-Seams Hygiene" spec (local-only
|
|
609
|
+
* working doc under docs/plans/, by that title) for the flexibility story.
|
|
610
|
+
*/
|
|
611
|
+
export interface HostGovernance {
|
|
612
|
+
/** Read the current governance state blob for a tool (installed/enabled/block/approvals). */
|
|
613
|
+
getGovernanceState(toolId: string): Promise<ToolGovernanceState | undefined>;
|
|
614
|
+
listForProject(projectRoot: string): Promise<ToolGovernanceState[]>;
|
|
615
|
+
queryAudit(toolId: string, filter?: unknown): Promise<AuditEntry[]>;
|
|
616
|
+
recordInstallation(toolId: string, record: InstallationRecord): Promise<void>;
|
|
617
|
+
recordApprovalDecision(toolId: string, decision: ApprovalDecision): Promise<void>;
|
|
618
|
+
setBlock(toolId: string, blocked: boolean, reason?: string): Promise<void>;
|
|
619
|
+
/** Enforcement helper (used by run paths or Cloud before acting on a tool). */
|
|
620
|
+
checkAllowed(toolId: string, action: 'install' | 'enable' | 'run-remediation' | 'run-simulation'): Promise<boolean>;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Host-owned audit plane (hostPlanes.audit). Tools append per-tool audit
|
|
624
|
+
* entries and query them back; the host persists them (Cloud primary, OSS
|
|
625
|
+
* compat via tool_state). Cloud may additionally chain entries into its
|
|
626
|
+
* WORM/tamper-evident log via {@link HostAudit.exportForCloud}.
|
|
627
|
+
*/
|
|
628
|
+
export interface HostAudit {
|
|
629
|
+
/** Append one audit entry for `toolId` (host persists it). */
|
|
630
|
+
append(toolId: string, entry: ToolAuditEntry): Promise<void>;
|
|
631
|
+
/** Read back `toolId`'s audit entries, optionally narrowed by `filter`. */
|
|
632
|
+
query(toolId: string, filter?: unknown): Promise<ToolAuditEntry[]>;
|
|
633
|
+
/** Best-effort linkage point for Cloud's WORM/tamper-evident audit chain. */
|
|
634
|
+
exportForCloud?(...args: unknown[]): Promise<unknown>;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Host-owned entitlements plane (hostPlanes.entitlements). Tools check whether
|
|
638
|
+
* an action is licensed, record usage for metering, and read the current
|
|
639
|
+
* license state. OSS hosts may supply permissive compat implementations.
|
|
640
|
+
*/
|
|
641
|
+
export interface HostEntitlements {
|
|
642
|
+
/** Resolve the entitlement status for `toolId` (optionally for a specific `action`). */
|
|
643
|
+
check(toolId: string, action?: string): Promise<EntitlementStatus>;
|
|
644
|
+
/** Record a usage event for `toolId` (metering / quota accounting). */
|
|
645
|
+
recordUsage(toolId: string, usage: UsageRecord): Promise<void>;
|
|
646
|
+
/** Read the current license state for `toolId`, or `undefined` if unknown. */
|
|
647
|
+
getLicenseState(toolId: string): Promise<LicenseState | undefined>;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Lightweight / forward-compatible record types for the host-owned
|
|
651
|
+
* governance/entitlements/audit plane.
|
|
652
|
+
*
|
|
653
|
+
* These are intentionally minimal in the first cut. Most fields are either
|
|
654
|
+
* opaque to the CLI today or will be interpreted by Cloud/Community surfaces.
|
|
655
|
+
* The host (via hostPlanes seams) performs serialization into the existing
|
|
656
|
+
* namespaced tool_state rows. See the governing spec for full rationale and
|
|
657
|
+
* evolution path.
|
|
658
|
+
*/
|
|
659
|
+
export type ToolGovernanceState = Record<string, unknown>;
|
|
660
|
+
/** Opaque record describing a tool installation (host/Cloud-interpreted). */
|
|
661
|
+
export type InstallationRecord = Record<string, unknown>;
|
|
662
|
+
/** Opaque record of an install/enable approval decision (host/Cloud-interpreted). */
|
|
663
|
+
export type ApprovalDecision = Record<string, unknown>;
|
|
664
|
+
/** Opaque governance audit entry recorded via {@link HostGovernance.queryAudit}. */
|
|
665
|
+
export type AuditEntry = Record<string, unknown>;
|
|
666
|
+
/** Opaque per-tool audit entry appended/queried via {@link HostAudit}. */
|
|
667
|
+
export type ToolAuditEntry = Record<string, unknown>;
|
|
668
|
+
/** Opaque entitlement-check result returned by {@link HostEntitlements.check}. */
|
|
669
|
+
export type EntitlementStatus = Record<string, unknown>;
|
|
670
|
+
/** Opaque usage event recorded via {@link HostEntitlements.recordUsage}. */
|
|
671
|
+
export type UsageRecord = Record<string, unknown>;
|
|
672
|
+
/** Opaque license-state snapshot returned by {@link HostEntitlements.getLicenseState}. */
|
|
673
|
+
export type LicenseState = Record<string, unknown>;
|
|
674
|
+
/**
|
|
675
|
+
* Tool error-handling contract.
|
|
676
|
+
*
|
|
677
|
+
* Tools have two paths for surfacing failure to the CLI dispatcher:
|
|
678
|
+
*
|
|
679
|
+
* 1. **Result-shaped return** — for expected business outcomes that
|
|
680
|
+
* callers may want to render with full UX (Ink, JSON, dashboard).
|
|
681
|
+
* Action handlers compute a `CommandResult` (`type: 'error'` is
|
|
682
|
+
* one variant) and pass it through `cli.render` / `cli.emitJson`,
|
|
683
|
+
* setting the exit code via `cli.setExitCode`. Both `simulation`
|
|
684
|
+
* and `graph` use this path for normal failures.
|
|
685
|
+
*
|
|
686
|
+
* 2. **Throw a `ToolError` subclass** — for unrecoverable / programmer
|
|
687
|
+
* conditions, or for known-error classes that the tool would
|
|
688
|
+
* rather let the central handler map to an exit code. The CLI's
|
|
689
|
+
* top-level `handleParseError` catches every `ToolError` that
|
|
690
|
+
* escapes a tool's action body and routes it through the
|
|
691
|
+
* canonical `mapToolErrorToExitCode` (in `@opensip-cli/contracts`).
|
|
692
|
+
*
|
|
693
|
+
* Which subclass to throw, by intent:
|
|
694
|
+
*
|
|
695
|
+
* - `ConfigurationError` — bad user input / missing config / wrong
|
|
696
|
+
* flag combination. Exit code: `CONFIGURATION_ERROR` (2).
|
|
697
|
+
* - `ValidationError` — a validated value failed an invariant.
|
|
698
|
+
* Exit code: `CONFIGURATION_ERROR` (2).
|
|
699
|
+
* - `NotFoundError` — a named entity (check, recipe, scenario)
|
|
700
|
+
* does not exist. Exit code: `CHECK_NOT_FOUND` (3).
|
|
701
|
+
* - `NetworkError` — remote call failed (e.g. `--report-to`).
|
|
702
|
+
* Exit code: `REPORT_FAILED` (4).
|
|
703
|
+
* - `TimeoutError` — an operation exceeded its deadline.
|
|
704
|
+
* Exit code: `RUNTIME_ERROR` (1).
|
|
705
|
+
* - `SystemError` — bootstrap-invariant violation or data
|
|
706
|
+
* corruption. Exit code: `RUNTIME_ERROR` (1).
|
|
707
|
+
* - bare `ToolError` — any other tool failure. Exit code:
|
|
708
|
+
* `RUNTIME_ERROR` (1).
|
|
709
|
+
*
|
|
710
|
+
* Tools that need to catch their own `ToolError` locally (e.g. to
|
|
711
|
+
* render in a non-Ink format) should still derive the exit code from
|
|
712
|
+
* `mapToolErrorToExitCode` rather than hardcoding the constant — that
|
|
713
|
+
* keeps a single source of truth for the policy.
|
|
714
|
+
*
|
|
715
|
+
* Plain `Error` instances thrown from a tool action body fall through
|
|
716
|
+
* to the data-driven `getErrorSuggestion` substring matcher, then to a
|
|
717
|
+
* generic `RUNTIME_ERROR`. Prefer the typed path.
|
|
718
|
+
*/
|
|
719
|
+
/**
|
|
720
|
+
* Inputs the host hands a tool's `scaffoldExamples` hook (ADR-0038): the
|
|
721
|
+
* project's detected/selected languages (and, optionally, the scaffolded check
|
|
722
|
+
* slugs). `languages` is `string[]` — core carries no language enum; the CLI
|
|
723
|
+
* passes its detected list through structurally.
|
|
724
|
+
*/
|
|
725
|
+
export interface ScaffoldContext {
|
|
726
|
+
readonly languages: readonly string[];
|
|
727
|
+
readonly slugs?: readonly string[];
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* One example file a tool contributes to `init` (ADR-0038). The host writes
|
|
731
|
+
* `content` to `userPluginDir(tool's domain, kind)/filename`. `kind` is a plain
|
|
732
|
+
* string matched against the tool's own `pluginLayout.userSubdirs` (never a
|
|
733
|
+
* host-side enum of `'checks'|'recipes'|…`). `stableId` is the pinned id embedded
|
|
734
|
+
* in `content` that drives stale-scaffolded detection.
|
|
735
|
+
*/
|
|
736
|
+
export interface ScaffoldFile {
|
|
737
|
+
readonly kind: string;
|
|
738
|
+
readonly filename: string;
|
|
739
|
+
readonly content: string;
|
|
740
|
+
readonly stableId: string;
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Bag for extension points and rarer/future hooks.
|
|
744
|
+
*
|
|
745
|
+
* ## Why this bag exists (discoverability)
|
|
746
|
+
*
|
|
747
|
+
* The main `Tool` interface is deliberately kept as "one cohesive interface"
|
|
748
|
+
* that every tool author implements. To prevent it from becoming a god
|
|
749
|
+
* interface over time, **new or experimental concerns should be added here**
|
|
750
|
+
* rather than as new top-level optional members.
|
|
751
|
+
*
|
|
752
|
+
* This is the official evolution path for the Tool contract.
|
|
753
|
+
*
|
|
754
|
+
* ## What belongs here
|
|
755
|
+
* - Optional lifecycle hooks (initialize, contributeScope, etc.)
|
|
756
|
+
* - Future capabilities, community distribution metadata, etc.
|
|
757
|
+
* - Host-plane participation declarations (governance / audit / entitlements)
|
|
758
|
+
*
|
|
759
|
+
* See the JSDoc on the `Tool` interface for the recommended grouping and
|
|
760
|
+
* the "Evolution Path" guidance. Also see ADR-0027 and ADR-0038.
|
|
761
|
+
*/
|
|
762
|
+
export interface ToolExtensionPoints {
|
|
763
|
+
readonly initialize?: () => Promise<void>;
|
|
764
|
+
readonly contributeScope?: () => ScopeContribution;
|
|
765
|
+
readonly collectReportData?: (scope: ToolScope) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
766
|
+
readonly sessionReplay?: ToolSessionReplayContribution;
|
|
767
|
+
readonly config?: ToolConfigContribution;
|
|
768
|
+
readonly capabilityRegistrars?: Readonly<Record<string, CapabilityRegistrar>>;
|
|
769
|
+
readonly fingerprintStrategy?: FingerprintStrategy;
|
|
770
|
+
readonly scaffoldExamples?: (ctx: ScaffoldContext) => readonly ScaffoldFile[];
|
|
771
|
+
readonly stableExampleIds?: () => readonly string[];
|
|
772
|
+
readonly scaffoldConfigBlock?: () => string;
|
|
773
|
+
readonly fitnessContractVersion?: string;
|
|
774
|
+
readonly graphContractVersion?: string;
|
|
775
|
+
readonly simulationContractVersion?: string;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* The contract every first-party, installed, or project-local tool implements
|
|
779
|
+
* (`fitness`, `simulation`, `graph`, …).
|
|
780
|
+
*
|
|
781
|
+
* A tool declares its metadata and `commandSpecs` (the **only** command surface).
|
|
782
|
+
* The host (`cli`) loads every tool through the same dynamic-import plugin path;
|
|
783
|
+
* nothing here distinguishes a bundled tool from an installed one (ADR-0027).
|
|
784
|
+
*
|
|
785
|
+
* ## Design note (architecture review)
|
|
786
|
+
*
|
|
787
|
+
* The surface is deliberately *rich and cohesive* rather than a minimal set of
|
|
788
|
+
* narrow interfaces. New or rare concerns are routed through the `extensionPoints`
|
|
789
|
+
* bag (or top-level optionals that predate the bag) + per-tool `*ContractVersion`
|
|
790
|
+
* fields (ADR-0046, ADR-0047). This keeps the core Tool contract stable while
|
|
791
|
+
* allowing independent evolution of fitness/graph/simulation surfaces. The trade-off
|
|
792
|
+
* (larger surface for tool authors, coordination for new capability *domains*)
|
|
793
|
+
* was accepted in favor of a single place to look for "what can a tool do?" and
|
|
794
|
+
* to avoid a proliferation of tiny marker interfaces. See the evolution guidance
|
|
795
|
+
* in the JSDoc below and in tool-lifecycle / capability docs.
|
|
796
|
+
*
|
|
797
|
+
* ## Contract Structure (for discoverability)
|
|
798
|
+
*
|
|
799
|
+
* The surface is intentionally one cohesive interface (see top-of-file comment).
|
|
800
|
+
* It is organized into these logical groups:
|
|
801
|
+
*
|
|
802
|
+
* ### Stable Core Surface (most tools will implement these)
|
|
803
|
+
* - `metadata`, `commands`, `pluginLayout`, `commandSpecs`
|
|
804
|
+
*
|
|
805
|
+
* ### Lifecycle & Host Integration (optional)
|
|
806
|
+
* - `initialize`, `contributeScope`, `collectReportData`, `sessionReplay`,
|
|
807
|
+
* `config`, `capabilityRegistrars`, `fingerprintStrategy`
|
|
808
|
+
*
|
|
809
|
+
* ### Scaffolding / `init` support (ADR-0038)
|
|
810
|
+
* - `scaffoldExamples`, `stableExampleIds`, `scaffoldConfigBlock`
|
|
811
|
+
*
|
|
812
|
+
* ### Evolution Path (strongly preferred for new concerns)
|
|
813
|
+
* - `extensionPoints` (see `ToolExtensionPoints` below)
|
|
814
|
+
*
|
|
815
|
+
* ## Future-Proofing
|
|
816
|
+
*
|
|
817
|
+
* Use the exported `TOOL_CONTRACT_VERSION` in your `contractVersion` field
|
|
818
|
+
* when you author a tool. New or experimental capabilities should go into
|
|
819
|
+
* `extensionPoints` rather than new top-level members.
|
|
820
|
+
*
|
|
821
|
+
* The host provides typed seams on `ToolCliContext` (including the typed
|
|
822
|
+
* `hostPlanes` bag for governance/audit/entitlements).
|
|
823
|
+
*/
|
|
824
|
+
export interface Tool {
|
|
825
|
+
readonly metadata: ToolMetadata;
|
|
826
|
+
/**
|
|
827
|
+
* Optional marker for which version of the Tool contract this
|
|
828
|
+
* implementation was authored against.
|
|
829
|
+
*
|
|
830
|
+
* Recommended usage:
|
|
831
|
+
* contractVersion: TOOL_CONTRACT_VERSION
|
|
832
|
+
*
|
|
833
|
+
* See the exported `TOOL_CONTRACT_VERSION` constant for rationale and
|
|
834
|
+
* future evolution notes. This field is purely advisory for now.
|
|
835
|
+
*/
|
|
836
|
+
readonly contractVersion?: string;
|
|
837
|
+
/**
|
|
838
|
+
* Metadata for every command this tool contributes. Used for --help
|
|
839
|
+
* listings and conflict detection. Actual handlers are mounted by
|
|
840
|
+
* the host.
|
|
841
|
+
*/
|
|
842
|
+
readonly commands: readonly ToolCommandDescriptor[];
|
|
843
|
+
/**
|
|
844
|
+
* Optional project-local plugin layout. Tools that support
|
|
845
|
+
* user-authored / npm plugins under `<project>/opensip-cli/<domain>/`
|
|
846
|
+
* declare `{ domain, userSubdirs }` here; the kernel's `discoverPlugins`
|
|
847
|
+
* / `loadAllPlugins` and the CLI's `plugin` command read it instead of
|
|
848
|
+
* hardcoding domain names (ADR-0009 corollary 1). Tools with no
|
|
849
|
+
* project-local plugins (e.g. graph) leave this undefined.
|
|
850
|
+
*/
|
|
851
|
+
readonly pluginLayout?: PluginLayout;
|
|
852
|
+
/**
|
|
853
|
+
* Declarative command surface (launch, north-star §5.4). The
|
|
854
|
+
* PREFERRED way a tool contributes commands: it returns one
|
|
855
|
+
* {@link CommandSpec} per subcommand and the host's `mountCommandSpec`
|
|
856
|
+
* (cli, Phase 1) translates each into a wired Commander command — the tool
|
|
857
|
+
* never touches Commander. Specs are typed against the concrete host
|
|
858
|
+
* {@link ToolCliContext} (the kernel's default `CommandContext` marker isn't
|
|
859
|
+
* assignable to it), so a tool authors them via
|
|
860
|
+
* `defineCommand<TOpts, ToolCliContext>(...)`.
|
|
861
|
+
*
|
|
862
|
+
* The host mounts each spec via `mountCommandSpec` (the ONLY command surface
|
|
863
|
+
* as of launch — `register()` was removed). A tool that declares no
|
|
864
|
+
* `commandSpecs` contributes no commands (a mis-declaration the host surfaces
|
|
865
|
+
* loudly via `cli.tool.no_command_surface`).
|
|
866
|
+
*
|
|
867
|
+
* Typed `CommandSpec<unknown, ToolCliContext>` (the kernel cannot name the
|
|
868
|
+
* per-spec `TOpts`); the host's `mountCommandSpec` narrows each spec.
|
|
869
|
+
*/
|
|
870
|
+
readonly commandSpecs?: readonly CommandSpec<unknown, ToolCliContext>[];
|
|
871
|
+
/**
|
|
872
|
+
* Optional one-time initialization. Called by the CLI before any of
|
|
873
|
+
* the tool's commands run. Use it to register sub-packages (check
|
|
874
|
+
* packs, scenario packs), language adapters, etc.
|
|
875
|
+
*
|
|
876
|
+
* The CLI calls initialize() at most once per process. Tools that
|
|
877
|
+
* need lazy init (e.g. fitness, where ensureChecksLoaded is wired
|
|
878
|
+
* deep into command handlers) can leave this undefined and run
|
|
879
|
+
* setup inside their command handlers instead.
|
|
880
|
+
*/
|
|
881
|
+
readonly initialize?: () => Promise<void>;
|
|
882
|
+
/**
|
|
883
|
+
* Optional per-run subscope contribution. Called by the CLI's
|
|
884
|
+
* pre-action-hook AFTER constructing the per-invocation scope and
|
|
885
|
+
* BEFORE `enterScope` makes it visible to tool action bodies. Each
|
|
886
|
+
* registered tool is invoked once per CLI invocation; the kernel
|
|
887
|
+
* `Object.assign`s the returned contribution onto the scope (D7: tool
|
|
888
|
+
* subscopes via module augmentation).
|
|
889
|
+
*
|
|
890
|
+
* Inversion of control (audit 2026-05-29, M4): the tool RETURNS its
|
|
891
|
+
* subscope rather than mutating a passed-in `RunScope`. This keeps the
|
|
892
|
+
* `Tool` contract free of any `RunScope` reference (breaking the
|
|
893
|
+
* RunScope⟷Tool type cycle) and removes shared-mutable-state from the
|
|
894
|
+
* extension API.
|
|
895
|
+
*
|
|
896
|
+
* Tools augment `ScopeContribution` from their own package:
|
|
897
|
+
*
|
|
898
|
+
* declare module '@opensip-cli/core' {
|
|
899
|
+
* interface ScopeContribution {
|
|
900
|
+
* simulation?: { scenarios: Registry<RunnableScenario>; ... };
|
|
901
|
+
* }
|
|
902
|
+
* }
|
|
903
|
+
*
|
|
904
|
+
* and return their slot here:
|
|
905
|
+
*
|
|
906
|
+
* contributeScope() {
|
|
907
|
+
* return { simulation: { scenarios: new Registry(...), ... } };
|
|
908
|
+
* }
|
|
909
|
+
*
|
|
910
|
+
* The kernel never inspects the slot — it just installs it. Slots are
|
|
911
|
+
* optional so a graph-only run carries no `scope.simulation`, and vice
|
|
912
|
+
* versa. `ScopeContribution` is empty in core; every member arrives via
|
|
913
|
+
* tool augmentation, and `ToolScope`/`RunScope` extend it for reads.
|
|
914
|
+
*
|
|
915
|
+
* Default behavior (when undefined): the tool contributes no subscope.
|
|
916
|
+
* Fitness, today, carries no per-run subscope state and leaves this
|
|
917
|
+
* undefined.
|
|
918
|
+
*/
|
|
919
|
+
readonly contributeScope?: () => ScopeContribution;
|
|
920
|
+
/**
|
|
921
|
+
* Optional report-data contribution (audit 2026-05-29, L2). The CLI
|
|
922
|
+
* is the report composition root: it gathers generic sessions, then
|
|
923
|
+
* walks the tool registry calling this hook and merges each tool's
|
|
924
|
+
* contribution into the HTML report input. A tool returns ITS OWN inputs
|
|
925
|
+
* to the HTML report (fitness: check/recipe catalogs; graph: its
|
|
926
|
+
* catalog) — keyed by the field names `generateDashboardHtml` consumes.
|
|
927
|
+
*
|
|
928
|
+
* Returns an opaque `Record<string, unknown>` so the kernel carries no
|
|
929
|
+
* tool/report-renderer vocabulary; the CLI `Object.assign`s it onto the
|
|
930
|
+
* `DashboardInput`. Tools that contribute nothing leave this undefined.
|
|
931
|
+
* Receives the Tool-facing `ToolScope` (datastore, projectContext, …).
|
|
932
|
+
*/
|
|
933
|
+
readonly collectReportData?: (scope: ToolScope) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
934
|
+
/**
|
|
935
|
+
* Optional session replay contribution. The CLI owns the generic
|
|
936
|
+
* `sessions show` command, while each tool owns decoding its opaque
|
|
937
|
+
* `StoredSession.payload` projection into renderable replay data.
|
|
938
|
+
*
|
|
939
|
+
* Core keeps the hook structural (`unknown` return) so it does not depend on
|
|
940
|
+
* `@opensip-cli/contracts`; the CLI narrows the returned value at the
|
|
941
|
+
* composition boundary.
|
|
942
|
+
*/
|
|
943
|
+
readonly sessionReplay?: ToolSessionReplayContribution;
|
|
944
|
+
/**
|
|
945
|
+
* Optional namespaced config contribution (launch, ADR-0023). A
|
|
946
|
+
* tool owning a top-level block (`graph:`/`fitness:`/`simulation:`) declares
|
|
947
|
+
* its Zod schema here as a `ToolConfigDeclaration` (from
|
|
948
|
+
* `@opensip-cli/config`). The composition root composes every tool's
|
|
949
|
+
* `config` into one strict whole-document schema, validates the config file
|
|
950
|
+
* once before dispatch, and exposes the resolved config back via the scope.
|
|
951
|
+
* Kernel-side {@link ToolConfigContribution} carrier (core carries no Zod);
|
|
952
|
+
* the CLI narrows it. Undefined ⇒ no config block.
|
|
953
|
+
*/
|
|
954
|
+
readonly config?: ToolConfigContribution;
|
|
955
|
+
/**
|
|
956
|
+
* Optional capability-domain registrars (launch, §5.3), keyed by
|
|
957
|
+
* domain id. A tool that DECLARES domains in its manifest
|
|
958
|
+
* (`ToolPluginManifest.capabilities`) supplies the REAL registrar for each
|
|
959
|
+
* here. The host registers each manifest domain with a deferred placeholder,
|
|
960
|
+
* then replaces it via `CapabilityRegistry.setRegistrar` once this module
|
|
961
|
+
* loads. The registrar registers a routed contribution into the tool's own
|
|
962
|
+
* registry. Undefined ⇒ no declared domains.
|
|
963
|
+
*/
|
|
964
|
+
readonly capabilityRegistrars?: Readonly<Record<string, CapabilityRegistrar>>;
|
|
965
|
+
/**
|
|
966
|
+
* Optional fingerprint strategy for the host-owned baseline/ratchet plane
|
|
967
|
+
* (ADR-0036). Populates `Signal.fingerprint`; the plane treats the result
|
|
968
|
+
* opaquely. Undefined ⇒ host `defaultFingerprintStrategy`. Stamping happens at
|
|
969
|
+
* envelope construction: pass the SAME strategy as
|
|
970
|
+
* `BuildEnvelopeInput.fingerprintStrategy` to `buildSignalEnvelope`
|
|
971
|
+
* (`@opensip-cli/contracts`), which stamps every signal (host default when
|
|
972
|
+
* omitted) so a built envelope is gate-ready by construction. This field is
|
|
973
|
+
* the tool's DECLARATION of that identity for the plane's documentation and
|
|
974
|
+
* future host consumers; the envelope builder is where it takes effect.
|
|
975
|
+
* Changing a declared strategy is a deliberate, documented re-capture.
|
|
976
|
+
*/
|
|
977
|
+
readonly fingerprintStrategy?: FingerprintStrategy;
|
|
978
|
+
/**
|
|
979
|
+
* Optional `init`-scaffold contribution (ADR-0038): the example files this tool
|
|
980
|
+
* writes for a project, given its detected languages. The host writes each
|
|
981
|
+
* returned file under `userPluginDir(<this tool's pluginLayout.domain>,
|
|
982
|
+
* file.kind)/file.filename`. Undefined ⇒ this tool scaffolds no examples (e.g.
|
|
983
|
+
* `graph`). The host owns the directory layout (from `pluginLayout.userSubdirs`)
|
|
984
|
+
* + the document header + `targets:`; the tool owns the example bytes + ids.
|
|
985
|
+
*/
|
|
986
|
+
readonly scaffoldExamples?: (ctx: ScaffoldContext) => readonly ScaffoldFile[];
|
|
987
|
+
/**
|
|
988
|
+
* The tool's COMPLETE set of stable example ids across EVERY language it can
|
|
989
|
+
* scaffold — NOT just the languages in any one `ScaffoldContext`. Drives
|
|
990
|
+
* stale-scaffolded detection (`file-classifier.ts`): a stale
|
|
991
|
+
* `example-check-python.mjs` left in a now-TS-only project must still be
|
|
992
|
+
* recognised, which needs the full id universe independent of the project's
|
|
993
|
+
* currently-detected languages.
|
|
994
|
+
*/
|
|
995
|
+
readonly stableExampleIds?: () => readonly string[];
|
|
996
|
+
/**
|
|
997
|
+
* Optional contribution of the tool's namespaced config block for the
|
|
998
|
+
* scaffolded `opensip-cli.config.yml` (ADR-0038 Phase 3). Undefined ⇒ the host
|
|
999
|
+
* renders the block from the tool's `ToolConfigDeclaration` defaults (or omits
|
|
1000
|
+
* it). The host always renders the document header + the `targets:` section.
|
|
1001
|
+
*/
|
|
1002
|
+
readonly scaffoldConfigBlock?: () => string;
|
|
1003
|
+
/**
|
|
1004
|
+
* Bag for extension points and rarer/future hooks.
|
|
1005
|
+
*
|
|
1006
|
+
* New concerns should go here (see `ToolExtensionPoints` JSDoc) rather than
|
|
1007
|
+
* additional top-level optionals. This is the evolution path for the Tool
|
|
1008
|
+
* contract.
|
|
1009
|
+
*/
|
|
1010
|
+
readonly extensionPoints?: ToolExtensionPoints;
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Plugin export shape for npm packages whose package.json declares
|
|
1014
|
+
* `opensipTools.kind === 'tool'`. The package's main entry must export
|
|
1015
|
+
* a `tool` symbol of this shape.
|
|
1016
|
+
*/
|
|
1017
|
+
export interface ToolPluginExports {
|
|
1018
|
+
readonly tool: Tool;
|
|
1019
|
+
}
|
|
1020
|
+
export {};
|
|
1021
|
+
//# sourceMappingURL=types.d.ts.map
|