Skip to content

Fix wfctl validate --plugin-dir ignoring types from plugin.json capabilities object#319

Merged
intel352 merged 3 commits intomainfrom
copilot/fix-wfctl-validate-plugin-dir
Mar 12, 2026
Merged

Fix wfctl validate --plugin-dir ignoring types from plugin.json capabilities object#319
intel352 merged 3 commits intomainfrom
copilot/fix-wfctl-validate-plugin-dir

Conversation

Copy link
Contributor

Copilot AI commented Mar 12, 2026

wfctl validate --plugin-dir failed to recognize module/step/trigger types in external plugins whose plugin.json uses the v0.3.0+ nested capabilities object format, causing false "unknown type" validation errors.

Root Cause

LoadPluginTypesFromDir in schema/schema.go only read top-level moduleTypes/stepTypes/triggerTypes fields. The v0.3.0+ registry manifest format nests these under a capabilities object:

{
  "capabilities": {
    "moduleTypes": ["authz.casbin"],
    "stepTypes": ["step.authz_check_casbin"],
    "triggerTypes": []
  }
}

Changes

  • schema/schema.go: Added pluginManifestCapabilities struct for the nested format; added it as an optional Capabilities field on pluginManifestTypes; updated LoadPluginTypesFromDir to register types from both the flat (legacy) and nested capabilities formats.
  • schema/schema_test.go: Added TestLoadPluginTypesFromDir_CapabilitiesFormat covering the nested format.
  • cmd/wfctl/main_test.go: Added TestRunValidatePluginDirCapabilities end-to-end integration test verifying wfctl validate --plugin-dir passes for configs using types declared via the capabilities object.
Original prompt

This section details on the original issue you should resolve

<issue_title>wfctl validate --plugin-dir does not load types from plugin.json capabilities</issue_title>
<issue_description>## Summary

wfctl validate --plugin-dir <dir> does not recognize module or step types declared in external plugin plugin.json manifests. Configs that use external plugin types (e.g., authz.casbin, step.authz_check_casbin) always fail validation unless --skip-unknown-types is used.

Reproduction

# Plugin directory structure:
# plugins/workflow-plugin-authz/
#   plugin.json          (declares authz.casbin, step.authz_check_casbin, etc.)
#   workflow-plugin-authz (binary, downloaded from release)

$ wfctl validate --plugin-dir plugins config.yaml
error: 1 config(s) failed validation

$ wfctl validate --skip-unknown-types config.yaml
PASS config.yaml (5 modules, 1 workflows, 0 triggers)

plugin.json

The manifest uses the v0.3.0+ capabilities format:

{
    "name": "workflow-plugin-authz",
    "version": "1.0.0",
    "type": "external",
    "capabilities": {
        "configProvider": false,
        "moduleTypes": ["authz.casbin"],
        "stepTypes": [
            "step.authz_check_casbin",
            "step.authz_add_policy",
            "step.authz_remove_policy",
            "step.authz_role_assign"
        ],
        "triggerTypes": []
    }
}

Expected Behavior

wfctl validate --plugin-dir plugins should:

  1. Scan the plugin directory for subdirectories containing plugin.json
  2. Read moduleTypes, stepTypes, and triggerTypes from the manifest
  3. Register those types as known so they don't trigger "unknown type" validation errors

The binary should NOT need to be executed for type discovery — the manifest already declares everything needed.

Environment

  • wfctl v0.3.36
  • workflow-plugin-authz v0.3.0
  • macOS arm64</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

…ect in LoadPluginTypesFromDir

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix wfctl validate command to load types from plugin.json Fix wfctl validate --plugin-dir ignoring types from plugin.json capabilities object Mar 12, 2026
Copilot AI requested a review from intel352 March 12, 2026 19:38
@intel352 intel352 marked this pull request as ready for review March 12, 2026 19:58
Copilot AI review requested due to automatic review settings March 12, 2026 19:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes wfctl validate --plugin-dir falsely reporting “unknown type” for external plugins whose plugin.json uses the registry-style nested capabilities object by loading types from both legacy flat fields and the nested format.

Changes:

  • Extend schema.LoadPluginTypesFromDir to register module/step/trigger/workflow handler types from capabilities.* in addition to top-level fields.
  • Add unit test coverage for the nested capabilities manifest format.
  • Add an end-to-end wfctl validate --plugin-dir test covering the nested capabilities format.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
schema/schema.go Adds support for reading types from a nested capabilities object in plugin.json during validation.
schema/schema_test.go Adds a unit test validating type registration from the nested capabilities format.
cmd/wfctl/main_test.go Adds an integration test verifying wfctl validate --plugin-dir succeeds with nested capabilities manifests.

Comment on lines 388 to +394
type pluginManifestTypes struct {
ModuleTypes []string `json:"moduleTypes"`
StepTypes []string `json:"stepTypes"`
TriggerTypes []string `json:"triggerTypes"`
WorkflowTypes []string `json:"workflowTypes"`
ModuleTypes []string `json:"moduleTypes"`
StepTypes []string `json:"stepTypes"`
TriggerTypes []string `json:"triggerTypes"`
WorkflowTypes []string `json:"workflowTypes"`
Capabilities *pluginManifestCapabilities `json:"capabilities,omitempty"`
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadPluginTypesFromDir unmarshals plugin.json into pluginManifestTypes. With the new Capabilities *pluginManifestCapabilities field, unmarshalling will fail (and the manifest will be skipped entirely) if a plugin.json uses the engine/internal manifest format where capabilities is a JSON array (see plugin.PluginManifest.Capabilities []CapabilityDecl). That would prevent registering the otherwise-valid top-level moduleTypes/stepTypes/etc. Consider making Capabilities a json.RawMessage (or custom UnmarshalJSON) and only decoding it as an object when it’s actually an object, ignoring the array form.

Copilot uses AI. Check for mistakes.
Comment on lines +396 to 403
// pluginManifestCapabilities holds the nested capabilities object used in the
// v0.3.0+ external plugin.json format (e.g. from wfctl plugin install).
type pluginManifestCapabilities struct {
ModuleTypes []string `json:"moduleTypes"`
StepTypes []string `json:"stepTypes"`
TriggerTypes []string `json:"triggerTypes"`
WorkflowHandlers []string `json:"workflowHandlers"`
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says the nested capabilities object format is used by external plugin.json “(e.g. from wfctl plugin install)”, but wfctl plugin install currently writes a flattened plugin.json with top-level moduleTypes/stepTypes/triggerTypes (see writeInstalledManifest in cmd/wfctl/plugin_install.go). Suggest updating this comment to reflect that this nested format corresponds to the registry manifest shape (or older installs), not the current installer output.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link

github-actions bot commented Mar 12, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:244: parsing iteration count: invalid syntax
baseline-bench.txt:318245: parsing iteration count: invalid syntax
baseline-bench.txt:638781: parsing iteration count: invalid syntax
baseline-bench.txt:957973: parsing iteration count: invalid syntax
baseline-bench.txt:1244336: parsing iteration count: invalid syntax
baseline-bench.txt:1544214: parsing iteration count: invalid syntax
benchmark-results.txt:244: parsing iteration count: invalid syntax
benchmark-results.txt:311912: parsing iteration count: invalid syntax
benchmark-results.txt:614613: parsing iteration count: invalid syntax
benchmark-results.txt:917548: parsing iteration count: invalid syntax
benchmark-results.txt:1184990: parsing iteration count: invalid syntax
benchmark-results.txt:1497456: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │       benchmark-results.txt        │
                            │       sec/op       │    sec/op     vs base              │
InterpreterCreation-4               6.777m ± 55%   6.419m ± 63%       ~ (p=0.699 n=6)
ComponentLoad-4                     3.569m ±  6%   3.507m ±  4%       ~ (p=0.240 n=6)
ComponentExecute-4                  2.029µ ±  2%   2.017µ ±  3%       ~ (p=0.095 n=6)
PoolContention/workers-1-4          1.112µ ±  1%   1.098µ ±  7%       ~ (p=0.310 n=6)
PoolContention/workers-2-4          1.095µ ±  1%   1.083µ ±  1%  -1.14% (p=0.030 n=6)
PoolContention/workers-4-4          1.099µ ±  3%   1.094µ ±  1%       ~ (p=0.167 n=6)
PoolContention/workers-8-4          1.104µ ±  3%   1.095µ ±  3%       ~ (p=0.074 n=6)
PoolContention/workers-16-4         1.135µ ±  3%   1.100µ ±  1%       ~ (p=0.331 n=6)
ComponentLifecycle-4                3.697m ±  1%   3.497m ±  1%  -5.42% (p=0.002 n=6)
SourceValidation-4                  2.442µ ±  1%   2.306µ ±  1%  -5.55% (p=0.002 n=6)
RegistryConcurrent-4                862.2n ±  2%   780.3n ±  4%  -9.50% (p=0.002 n=6)
LoaderLoadFromString-4              3.740m ±  1%   3.504m ±  1%  -6.31% (p=0.002 n=6)
geomean                             19.12µ         18.46µ        -3.46%

                            │ baseline-bench.txt │        benchmark-results.txt         │
                            │        B/op        │     B/op      vs base                │
InterpreterCreation-4               1.944Mi ± 0%   1.944Mi ± 0%       ~ (p=0.738 n=6)
ComponentLoad-4                     2.097Mi ± 0%   2.097Mi ± 0%       ~ (p=0.965 n=6)
ComponentExecute-4                  1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4         1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                2.099Mi ± 0%   2.099Mi ± 0%       ~ (p=1.000 n=6)
SourceValidation-4                  1.984Ki ± 0%   1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                1.133Ki ± 0%   1.133Ki ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4              2.099Mi ± 0%   2.099Mi ± 0%       ~ (p=0.909 n=6)
geomean                             15.05Ki        15.05Ki       +0.00%
¹ all samples are equal

                            │ baseline-bench.txt │        benchmark-results.txt        │
                            │     allocs/op      │  allocs/op   vs base                │
InterpreterCreation-4                15.09k ± 0%   15.09k ± 0%       ~ (p=1.000 n=6)
ComponentLoad-4                      17.43k ± 0%   17.43k ± 0%       ~ (p=1.000 n=6)
ComponentExecute-4                    25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4           25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                 17.48k ± 0%   17.48k ± 0%       ~ (p=1.000 n=6) ¹
SourceValidation-4                    32.00 ± 0%    32.00 ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                  2.000 ± 0%    2.000 ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4               17.47k ± 0%   17.47k ± 0%       ~ (p=1.000 n=6) ¹
geomean                               181.2         181.2       +0.00%
¹ all samples are equal

pkg: github.com/GoCodeAlone/workflow/middleware
                                  │ baseline-bench.txt │       benchmark-results.txt       │
                                  │       sec/op       │   sec/op     vs base              │
CircuitBreakerDetection-4                  292.2n ± 3%   287.5n ± 1%  -1.63% (p=0.004 n=6)
CircuitBreakerExecution_Success-4          22.54n ± 1%   22.50n ± 0%       ~ (p=0.080 n=6)
CircuitBreakerExecution_Failure-4          64.40n ± 0%   64.47n ± 0%       ~ (p=0.227 n=6)
geomean                                    75.13n        74.72n       -0.55%

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │        B/op        │    B/op     vs base                │
CircuitBreakerDetection-4                 144.0 ± 0%     144.0 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │     allocs/op      │ allocs/op   vs base                │
CircuitBreakerDetection-4                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │       sec/op       │    sec/op     vs base              │
JQTransform_Simple-4                     896.5n ± 28%   927.0n ± 20%       ~ (p=0.937 n=6)
JQTransform_ObjectConstruction-4         1.473µ ± 26%   1.475µ ±  1%       ~ (p=0.965 n=6)
JQTransform_ArraySelect-4                3.364µ ±  1%   3.307µ ±  1%  -1.69% (p=0.009 n=6)
JQTransform_Complex-4                    38.50µ ±  1%   37.66µ ±  2%  -2.20% (p=0.015 n=6)
JQTransform_Throughput-4                 1.803µ ±  1%   1.791µ ±  1%       ~ (p=0.240 n=6)
SSEPublishDelivery-4                     62.60n ±  0%   62.44n ±  1%       ~ (p=0.372 n=6)
geomean                                  1.638µ         1.634µ        -0.24%

                                 │ baseline-bench.txt │        benchmark-results.txt         │
                                 │        B/op        │     B/op      vs base                │
JQTransform_Simple-4                   1.273Ki ± 0%     1.273Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4       1.773Ki ± 0%     1.773Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4              2.625Ki ± 0%     2.625Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                  16.22Ki ± 0%     16.22Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4               1.984Ki ± 0%     1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%       0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²                 +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │     allocs/op      │ allocs/op   vs base                │
JQTransform_Simple-4                     10.00 ± 0%     10.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4         15.00 ± 0%     15.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4                30.00 ± 0%     30.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                    324.0 ± 0%     324.0 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4                 17.00 ± 0%     17.00 ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
                                    │ baseline-bench.txt │       benchmark-results.txt       │
                                    │       sec/op       │   sec/op     vs base              │
SchemaValidation_Simple-4                    1.121µ ± 6%   1.131µ ± 4%       ~ (p=0.589 n=6)
SchemaValidation_AllFields-4                 1.689µ ± 7%   1.704µ ± 6%       ~ (p=0.699 n=6)
SchemaValidation_FormatValidation-4          1.594µ ± 2%   1.599µ ± 1%       ~ (p=0.513 n=6)
SchemaValidation_ManySchemas-4               1.813µ ± 2%   1.847µ ± 4%       ~ (p=0.240 n=6)
geomean                                      1.529µ        1.544µ       +0.99%

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │        B/op        │    B/op     vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │     allocs/op      │ allocs/op   vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
                                   │ baseline-bench.txt │       benchmark-results.txt        │
                                   │       sec/op       │    sec/op     vs base              │
EventStoreAppend_InMemory-4                1.326µ ± 17%   1.276µ ± 17%       ~ (p=0.818 n=6)
EventStoreAppend_SQLite-4                  1.337m ±  3%   1.366m ±  7%       ~ (p=0.310 n=6)
GetTimeline_InMemory/events-10-4           14.33µ ±  5%   14.21µ ±  5%       ~ (p=0.132 n=6)
GetTimeline_InMemory/events-50-4           78.96µ ± 19%   79.66µ ± 14%       ~ (p=0.240 n=6)
GetTimeline_InMemory/events-100-4          128.8µ ±  1%   128.3µ ±  1%       ~ (p=0.699 n=6)
GetTimeline_InMemory/events-500-4          663.5µ ±  1%   663.0µ ±  1%       ~ (p=0.589 n=6)
GetTimeline_InMemory/events-1000-4         1.361m ±  1%   1.367m ±  0%       ~ (p=0.093 n=6)
GetTimeline_SQLite/events-10-4             119.0µ ±  1%   110.8µ ±  2%  -6.92% (p=0.002 n=6)
GetTimeline_SQLite/events-50-4             266.2µ ±  1%   256.1µ ±  0%  -3.80% (p=0.002 n=6)
GetTimeline_SQLite/events-100-4            438.2µ ±  1%   433.1µ ±  0%  -1.17% (p=0.009 n=6)
GetTimeline_SQLite/events-500-4            1.839m ±  1%   1.844m ±  1%       ~ (p=0.394 n=6)
GetTimeline_SQLite/events-1000-4           3.626m ±  2%   3.584m ±  0%  -1.14% (p=0.002 n=6)
geomean                                    229.7µ         226.9µ        -1.22%

                                   │ baseline-bench.txt │        benchmark-results.txt         │
                                   │        B/op        │     B/op      vs base                │
EventStoreAppend_InMemory-4                  779.0 ± 8%     784.5 ± 8%       ~ (p=0.900 n=6)
EventStoreAppend_SQLite-4                  1.983Ki ± 3%   1.985Ki ± 2%       ~ (p=0.567 n=6)
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%   7.953Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%   46.62Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%   94.48Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%   472.8Ki ± 0%       ~ (p=1.000 n=6)
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%   944.3Ki ± 0%       ~ (p=0.494 n=6)
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%   16.74Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%   87.14Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%   175.4Ki ± 0%       ~ (p=0.455 n=6)
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%   846.1Ki ± 0%       ~ (p=0.123 n=6)
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%   1.639Mi ± 0%       ~ (p=0.870 n=6)
geomean                                    67.26Ki        67.31Ki       +0.06%
¹ all samples are equal

                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │     allocs/op      │  allocs/op   vs base                │
EventStoreAppend_InMemory-4                  7.000 ± 0%    7.000 ± 0%       ~ (p=1.000 n=6) ¹
EventStoreAppend_SQLite-4                    53.00 ± 0%    53.00 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-10-4             125.0 ± 0%    125.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4             653.0 ± 0%    653.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4           1.306k ± 0%   1.306k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4           6.514k ± 0%   6.514k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-1000-4          13.02k ± 0%   13.02k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-10-4               382.0 ± 0%    382.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4              1.852k ± 0%   1.852k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4             3.681k ± 0%   3.681k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4             18.54k ± 0%   18.54k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-1000-4            37.29k ± 0%   37.29k ± 0%       ~ (p=1.000 n=6) ¹
geomean                                     1.162k        1.162k       +0.00%
¹ all samples are equal

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

@intel352
Copy link
Contributor

@copilot apply changes based on the comments in this thread

…ject formats; update comments

Co-authored-by: intel352 <77607+intel352@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 12, 2026

@copilot apply changes based on the comments in this thread

Applied all three review comments in commit 30077e5:

  1. Capabilities field now uses json.RawMessage — when unmarshalling, the raw bytes are only decoded as a pluginManifestCapabilities object when they start with {. Manifests using the engine-internal array format ([{"name":"...","role":"..."}]) are silently skipped for the capabilities block, but their flat top-level moduleTypes/stepTypes/etc. are still registered. Added TestLoadPluginTypesFromDir_CapabilitiesArrayFormat to cover this case.

  2. Comments updated — removed the misleading reference to "wfctl plugin install" generating the nested capabilities format; updated both schema/schema.go and cmd/wfctl/main_test.go to clarify this is the registry manifest format, not the installer output.

@intel352 intel352 merged commit c174d89 into main Mar 12, 2026
11 checks passed
@intel352 intel352 deleted the copilot/fix-wfctl-validate-plugin-dir branch March 12, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wfctl validate --plugin-dir does not load types from plugin.json capabilities

3 participants