Skip to content

feat(cli): implement ossie convert base command#158

Open
QMalcolm wants to merge 10 commits into
qmalcolm--feat-registry-embeddingfrom
qmalcolm--feat-convert-base
Open

feat(cli): implement ossie convert base command#158
QMalcolm wants to merge 10 commits into
qmalcolm--feat-registry-embeddingfrom
qmalcolm--feat-convert-base

Conversation

@QMalcolm

@QMalcolm QMalcolm commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Stacked on #156

Summary

Implement the convert base command. This means that convert collects the input files, invokes the conversion command for a specified plugin using utilizing the invocation protocol, writes out the return data to files, and logs an warnings/errors returned by the conversion script.

Screen.Recording.2026-06-25.at.16.24.40.mov

@QMalcolm

Copy link
Copy Markdown
Contributor Author

@QMalcolm
QMalcolm force-pushed the qmalcolm--feat-registry-embedding branch from ff4755f to 548693b Compare June 24, 2026 18:36
@QMalcolm
QMalcolm force-pushed the qmalcolm--feat-convert-base branch from 5a38d95 to ecffb3b Compare June 24, 2026 19:13
@QMalcolm QMalcolm changed the title feat(cli): implement osi convert base command feat(cli): implement ossie convert base command Jun 24, 2026
QMalcolm added 9 commits June 24, 2026 16:29
CollectFiles walks an input file or directory, filters by accepted
extensions, enforces a max-size limit, and returns a map of
relative-path keys to file content (forward slashes on all platforms).

Single-file inputs bypass the extension filter — the user explicitly
chose the file, so the plugin's Accepts list is not applied.
Empty accepts means all files are included (used by from_osi which
has no Accepts field).

LoadPlugin exports the existing unexported loadPlugin, used when
--plugin bypasses name-based discovery.
Adds cli/internal/schema/ with the OSI JSON schema embedded via
//go:embed. Validate() accepts YAML or JSON, round-trips through
encoding/json to normalise yaml.v3 types to what jsonschema/v6
expects, then validates against the compiled schema.

The schema is compiled once in init() — a panic here indicates a
build defect (corrupted embed), not a runtime error.

New dependency: github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
(draft 2020-12 support, matching the schema's $schema declaration).
Wires together file collection (F2), plugin invocation (F3), schema
validation, and output writing into a working end-to-end convert
command.

Flow: resolve plugin by name or --plugin path → collect input files
→ invoke plugin with timeout context → validate to_osi output against
embedded OSI schema → write passing files to ossie-output/ → render
issues to stderr → exit non-zero on any error-severity issue.

Schema validation failures remove the offending file from output
(rather than writing it with a warning) — the spec says validate
before writing. Info-severity issues are suppressed unless --verbose.

parseMaxInputSize supports MB/GB suffixes (case-insensitive) and
raw byte counts. renderIssues formats each issue as:
  severity: message
  severity: path: message (when path is present)
cli/internal/schema/osi-schema.json was a committed copy of
core-spec/osi-schema.json that could drift silently.

The file is now gitignored and generated by `make prepare`, which
copies from the canonical source before any build or test step.
CI switches from bare go commands to make targets so the copy step
runs automatically in all environments.
Empty accepts means no extension filter — all files in the directory
are included. The godoc stated this but it was untested.
If all to_osi output files fail schema validation, resp.Files is
empty. Creating the output directory in that case leaves an empty
ossie-output/ on disk with no explanation. Guard os.MkdirAll behind
len(resp.Files) > 0 so the directory only appears when there is
something to write.
Consistent with Go error message conventions and the rest of the
codebase. Single quotes were a shell quoting style.
runConvert was a single function with 11 numbered sections.
Extract sections 2, 3, 9, and 10 into named functions so the
orchestrator reads as a clean sequence of calls:

  resolvePlugin  — discover or load plugin by path/name
  selectDirection — map --from/--to to direction + Direction struct
  validateOutput  — schema-validate to_osi files, remove invalid ones
  writeOutput     — create outDir and write response files to disk

Sections 4 (parseMaxInputSize), 5 (CollectFiles), 8 (Invoke), and
11 (renderIssues) were already named functions. Sections 1, 6, and 7
are too small to warrant extraction.
selectDirection and validateOutput were written against the pre-rename
field names (ToOSI/FromOSI, to_osi/from_osi). The direction string
mismatch in validateOutput was a silent bug — output validation was
never reached because "to_ossie" != "to_osi".
@QMalcolm
QMalcolm force-pushed the qmalcolm--feat-registry-embedding branch from b86452c to 97dde31 Compare June 24, 2026 21:31
@QMalcolm
QMalcolm force-pushed the qmalcolm--feat-convert-base branch from ca33024 to 5af2f09 Compare June 24, 2026 21:31
CollectFiles was doing two distinct things — single-file read and
directory walk — in one flat function body. Extracting the walk into
collectDir makes each path easier to follow and test independently.
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.

1 participant