Skip to content

fix(docplan): warn, not fail, when a markup converter is missing - #1622

Merged
HuiJun merged 5 commits into
developfrom
fix/markup-tool-missing-warning
Oct 28, 2026
Merged

HuiJun merged 5 commits into
developfrom
fix/markup-tool-missing-warning

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

What and why

Since #1562, examples/self-model/asciidoc/markup.sysml carries rep language "asciidoc" bodies, which the document planner parses through the external Asciidoctor.js converter (OPENSYSML_ASCIIDOCTOR, else asciidoctor-json on PATH). On a host without that converter, sysml -validate examples exited 2: planDiagnostic made every *docplan.Error an error, a missing converter included. The Validate action / From the tree job builds a bare sysml and validates examples/ with no doc toolchain, so it went red on every PR that triggered it.

A missing converter is now a validation warning that leaves the bodies unchecked; a converter that is found but fails stays an error; and a rendering, which needs the parsed body, still fails on a missing converter.

  • docplan.ErrorKind.Severity() is the one place that decides the severity of a planning error kind (markup-tool-missing → warning, everything else → error). planDiagnostic honours it, and the codes registry derives document-plan's per-member severities from it (Entry.KindSeverities / MemberSeverity), so -explain, the listings and the generated catalogue show document-plan-markup-tool-missing as a warning. No language is special-cased: any markup language's missing tool follows the rule.

  • docplan.Validate plans a document leniently: a body whose converter is missing is left unchecked and the rest of the document is still planned and checked (a paragraph whose only text is such a body is not reported as missing its text). One warning per language is reported at the first such body, counting the bodies it covers. docplan.Compile, which every renderer uses, is unchanged and stops at the body.

  • markup.ToolError now records whether OPENSYSML_ASCIIDOCTOR named the converter or the default was looked up on PATH, and says so; the js/wasip1 variant says truthfully that the host starts no process.

  • Docs (docs/manual/authoring.md, docs/reference/environment.md, the self-model README) describe the warning, the unchecked bodies, -warnings-as-errors and the strict rendering; catalogue regenerated; changelog fragment added.

  • A document holding what a document plan in another document reads of it is no longer written to the interface-record cache (Workspace.plannedElsewhereLocked): a document query definition, whose result expression the plan evaluates from the tree, and a prose body an external converter checks, whose verdict is the host's. Two defects fall out of this:

    • Pre-existing, masked by the old hard error: once the planner gets past the AsciiDoc body (with the converter installed, on bare develop too), sysml -validate examples reported document-plan-query-planning … query OpenSysMLDocument::MarkupLanguages has no result expression, because the workspace demotes document.sysml to its record within the run and the record carries no result expression. tests/model TestInterfaceRecordDifferential/examples/self-model fails the same way on origin/develop with OPENSYSML_ASCIIDOCTOR set. The example and the library query are correct; the record was.
    • A clean record written with the converter installed would have been served, unchecked, on a host without it (and the missing-converter warning would have been served after installing it).
  • The missing-converter warning is scoped to the document whose bodies are scanned: a plan that reads another document's outline leaves that document's unchecked bodies to its own plan.

.github/workflows/validate-action.yml and the example model are untouched.

Before (origin/develop, no converter)

$ OPENSYSML_ASCIIDOCTOR= PATH=/nonexistent sysml -validate examples/self-model
examples/self-model/asciidoc/markup.sysml:16:9: error[document-plan-markup-tool-missing]: document OpenSysMLAsciiDoc::MarkupNote content OpenSysMLAsciiDoc::MarkupNote carries a asciidoc body that could not be parsed: the AsciiDoc converter asciidoctor-json was not found; run ./scripts/download-doc-pdf-toolchain.sh and point OPENSYSML_ASCIIDOCTOR at build/doc-pdf/asciidoctor/asciidoctor-json.js
sysml: examples/self-model did not analyse cleanly; no check was made
$ echo $?
2

After

$ OPENSYSML_ASCIIDOCTOR= PATH=/nonexistent sysml -validate examples/self-model
examples/self-model/asciidoc/markup.sysml:16:9: warning[document-plan-markup-tool-missing]: document OpenSysMLAsciiDoc::MarkupNote carries 3 asciidoc bodies that were not checked, the first in content OpenSysMLAsciiDoc::MarkupNote: the AsciiDoc converter asciidoctor-json was not found on PATH (OPENSYSML_ASCIIDOCTOR is unset); run ./scripts/download-doc-pdf-toolchain.sh and point OPENSYSML_ASCIIDOCTOR at build/doc-pdf/asciidoctor/asciidoctor-json.js
        rep language "asciidoc" /* The architecture document is written in Markdown; this note
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
✓ package OpenSysMLAsciiDoc
… (eleven more packages)
✓ examples/self-model: no errors
$ echo $?
0

$ OPENSYSML_ASCIIDOCTOR= PATH=/nonexistent sysml -validate -warnings-as-errors examples/self-model
(same warning)
sysml: examples/self-model has warnings, which -warnings-as-errors judges errors; no check was made
$ echo $?
2

$ OPENSYSML_ASCIIDOCTOR= PATH=/nonexistent sysml -validate -format sarif examples/self-model | jq '.runs[0].results[] | [.level, .ruleId]'
["warning", "document-plan-markup-tool-missing"]

$ OPENSYSML_ASCIIDOCTOR= PATH=/nonexistent sysml examples/self-model/*.sysml examples/self-model/asciidoc/*.sysml -render-document OpenSysMLAsciiDoc::MarkupNote
(the warning, then)
sysml: document OpenSysMLAsciiDoc::MarkupNote content OpenSysMLAsciiDoc::MarkupNote carries a asciidoc body that could not be parsed: the AsciiDoc converter asciidoctor-json was not found on PATH (OPENSYSML_ASCIIDOCTOR is unset); run ./scripts/download-doc-pdf-toolchain.sh and point OPENSYSML_ASCIIDOCTOR at build/doc-pdf/asciidoctor/asciidoctor-json.js
$ echo $?
2

How it was verified

  • internal/ir/docplan: TestValidateLeavesBodiesOfMissingConverterUnchecked (one warning over three bodies, Severity() warning, the missing-text error after them still found, Compile still stops at the body with could not be parsed), TestValidateReportsOneWarningPerBody.
  • internal/ir/docplan/markup: the OPENSYSML_ASCIIDOCTOR names it / not found on PATH (OPENSYSML_ASCIIDOCTOR is unset) wording, the detail and failed forms.
  • internal/check/passes/document: TestDocumentPlanPassWarnsOfMissingMarkupConverterAndGoesOn (a warning with the code at the body, then the document-plan-missing-text error of the next paragraph).
  • internal/check/codes: KindSeverities well-formedness; Rows/Explain report document-plan-markup-tool-missing as a warning and …-failed as an error.
  • cmd/sysml: TestValidateWithoutMarkupConverterWarns — -validate over examples/self-model with the variable unset and an empty PATH exits 0 with exactly one warning carrying the code and the PATH wording; exits 2 under -warnings-as-errors; SARIF level warning; -render-document exits 2 with the same message. TestValidateWithMarkupConverterChecksBodies runs with the converter the environment names and wants no warning (skips without one, fails under OPENSYSML_REQUIRE_PDF_TOOLCHAIN).
  • internal/workspace/model TestExamplesAnalyseCleanly no longer skips over the unchecked bodies; it logs them, and fails under OPENSYSML_REQUIRE_PDF_TOOLCHAIN. TestInterfaceRecordRefusesExternallyCheckedBodies (converter missing and found) and TestInterfaceRecordRefusesQueryDefinitions pin the record refusals; tests/model TestInterfaceRecordDifferential passes over the self-model again.
  • internal/ir/docplan TestValidateWarnsOfItsOwnBodiesOnly: a Report whose Markdown body references Appendix::tables.detail warns of its own AsciiDoc body only; Appendix of its own.
  • Over the tracked examples/ (the ignored downloaded corpora excluded) with a fresh record cache: sysml -validate -format sarif exits 0 without the converter (one document-plan-markup-tool-missing warning) and exits 0 with it (no such warning); -format junit renders the warning as <failure type="warning">, as the JUnit writer renders every warning (pinned by validate_report_test) — unchanged here.

Gate on head 8ae69c1cd (this VM), then on 3553ede81 go vet ./..., internal/workspace/model, internal/ir/docplan, tests/model (plain and -race, with and without the converter) re-run green: gofmt -l . empty; go build ./... clean; go vet ./... clean; go test ./... exit 0 (every package ok, no failures); make lint (staticcheck + gosec) ✓ Lint passed; python3 scripts/changelog.py check clean; make diagnostics-catalogue regenerated docs/reference/diagnostics.md. With the toolchain installed (./scripts/download-doc-pdf-toolchain.sh, OPENSYSML_ASCIIDOCTOR=build/doc-pdf/asciidoctor/asciidoctor-json.js, OPENSYSML_REQUIRE_PDF_TOOLCHAIN=1): cmd/sysml TestValidateWith(out)MarkupConverter… and internal/workspace/model TestExamplesAnalyseCleanly/self-model/asciidoc/markup.sysml pass, sysml -validate -warnings-as-errors examples/self-model exits 0 with no warning.

Checklist

  • make test and make lint pass locally
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (see CONTRIBUTING.md)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (compliance rows need nothing: the census is counted at docs build)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/da63d131020142d0aaf4c5ea0aac8fc9
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/da63d131020142d0aaf4c5ea0aac8fc9?variant=devin
Requested by: @HuiJun

A rep language "asciidoc" body whose converter is not installed made
sysml -validate exit 2 over the model, so a host without the doc
toolchain could not validate examples/. The document pass now plans
documents leniently: a missing converter leaves the bodies unchecked
under one document-plan-markup-tool-missing warning per language,
naming the converter, whether OPENSYSML_ASCIIDOCTOR named it or PATH
was searched, and the remedy; -warnings-as-errors makes it a failure.
A converter that is found but fails stays an error, and a rendering,
which needs the body, still fails on a missing converter.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

…erter

A missing or failing converter answers to the host, not the document,
so the interface record cache held the verdict of one host for another:
a document validated without the converter kept its warning after the
converter was installed. Such a document is now unrecordable and is
analyzed again wherever it is next opened.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun marked this pull request as ready for review October 28, 2026 04:11
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits October 28, 2026 04:22
…dies loaded

A document plan in another document evaluates a query definition's
result expression from its tree and reads a prose body through the
host's converter, neither of which an interface record answers: with
document.sysml held as its record, the self-model's AsciiDoc note
failed to plan OpenSysMLDocument::MarkupLanguages, and a clean record
written with the converter installed would have stood on a host
without it. The record writer now refuses both, in place of refusing
only a document reported on its converter.

The missing-converter warning is scoped to the document whose bodies
are scanned: a plan reading another document's outline leaves that
document's unchecked bodies to its own plan.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
…he record writer

The record writer in workspace/libs cannot read queryplan: its tests and
lower's import libs, which closes an import cycle in test builds.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
devin-ai-integration[bot]

This comment was marked as resolved.

A converted body on an ordinary part is read by no plan, so its document
stays recordable; docplan.ReadsBody says whose bodies are. Comments
trimmed to the repository's two lines.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@HuiJun
HuiJun merged commit b37cbeb into develop Oct 28, 2026
33 checks passed
@HuiJun
HuiJun deleted the fix/markup-tool-missing-warning branch October 28, 2026 13:03
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