Skip to content

Expand deck diagnostics: cross-keyword rules, value-type checks, and summary-vector coverage - #51

Merged
magnesj merged 16 commits into
OPM:mainfrom
magnesj:main
Jun 29, 2026
Merged

Expand deck diagnostics: cross-keyword rules, value-type checks, and summary-vector coverage#51
magnesj merged 16 commits into
OPM:mainfrom
magnesj:main

Conversation

@magnesj

@magnesj magnesj commented Jun 29, 2026

Copy link
Copy Markdown
Member

Summary

This batch of changes substantially expands the diagnostic engine and summary-vector index coverage for the OPM Flow deck editor.

Diagnostics

  • Add positional value-type diagnostics (flag values that don't match a keyword's expected type per position).
  • Add requires/prohibits cross-keyword diagnostics.
  • Resolve deck_name aliases and suppress opm-common family containers.
  • Treat an indented unknown token under an active keyword as record body.
  • Don't require a closing / for variadic-record list keywords (VFP, RSVD).
  • Defer the missing-record-terminator diagnostic until the record is actually unterminated.
  • Suppress the wrong-section diagnostic after an INCLUDE.
  • Recognise UDQ names so they are not flagged as unknown keywords.

Summary-vector index

  • Expand opm-common PROBE deck_names into summary-vector index entries.
  • Emit directional X/Y/Z variants for KRNUM/IMBNUM region keywords.
  • Recognise L-modifier summary vectors and add an index-coverage worklist to the report.
  • Recognise region summary vectors qualified by a FIP region-set name.

Tooling & docs

  • Add scripts/build_keyword_index.py with unit tests.
  • Add an opm-tests corpus false-positive harness (corpus.test.ts).
  • Document the test suite and corpus harness in DEVELOPMENT.md.
  • Remove the unused boilerplate module.

magnesj added 16 commits June 28, 2026 16:16
Walk a local opm-tests clone (OPM_TESTS_DIR, default M:/gitroot/opm-tests),
run computeDiagnostics on every deck/include, and write a triage report
grouping suspected false positives by diagnostic type and keyword. Gated with
describe.skip when the corpus is absent so normal test runs are unaffected.
The generated corpus-report.md is gitignored.
User-defined quantity names begin with a data-type letter (A B C F G R S W)
followed by 'U' (WUOPRL, FU_VAR1, WU_WBHP). They are user-defined and never in
the keyword index, but appear legitimately as bare SUMMARY mnemonics and inside
ACTIONX/UDQ bodies. Recognise them by shape in computeDiagnostics.

Cuts unrecognised-keyword false positives on the opm-tests corpus from 525 to
287.
Decks routinely split sections across included files (e.g. RUNSPEC in the master
deck, the remaining sections pulled in via INCLUDE 'BASE'). When the master file
is analysed standalone we never see the section headers inside the include, so
the tracked section is stale and SCHEDULE keywords written after the INCLUDE were
wrongly flagged 'not valid in RUNSPEC'. Once an INCLUDE/IMPORT/GDFILE is seen,
suppress the wrong-section check until the next explicit section header.

Cuts wrong-section false positives on the opm-tests corpus from 54 to 8.
…ated

OPM Flow allows a record's terminating '/' to appear on a later line than its
values (MINPV / PINCH / SPECGRID / PLYSHLOG and many table keywords are written
this way). The per-line check flagged every such record as missing its '/'.

Track an 'open' record instead: a record with values but no '/' is held open;
a later '/' (standalone or trailing) closes it, and only a record still open at
the block boundary (next keyword, section header, or EOF) is flagged. This also
matches how OPM Flow itself parses — tokens are read until a '/'.

Cuts missing-record-terminator false positives on the opm-tests corpus from 157
to 0.
Region summary vectors can be qualified by a named FIP region set, written as
<region-vector>_<NAME> (ROIP_ABC, RPR__ABC). The base is an R-prefixed vector in
the index; the _<NAME> qualifier is user-defined so the full token is never in
the index. Recognise this form so it is not flagged as an unknown keyword.

Cuts unrecognised-keyword false positives on the opm-tests corpus from 287 to
212 (total 771 -> 256 since the harness was added).
VFPPROD / VFPINJ (and other variadic-record keywords like RSVD) are classified
'list' but their table-style final record is closed by its own per-record '/',
with no separate standalone list terminator. They were wrongly flagged as
missing the '/' to close the record list. Skip the list/array close-terminator
check for variadic-record keywords.

Cuts missing-list/array-terminator false positives on the opm-tests corpus from
27 to 12.
OPM Flow only recognises keywords in column 1, so an indented token that is not
a known keyword cannot be one — it is body content of the active block. A single
well name on its own indented line under a SUMMARY vector ('  PROD2 /') was
matching the keyword pattern and, when the vector did not 'expect more records',
being mis-flagged as an unknown keyword. Treat such indented non-keyword tokens
as record body. Column-1 detection for indented *known* keywords is preserved.

Cuts unrecognised-keyword false positives on the opm-tests corpus from 212 to
196.
…to report

Completion-level (trailing L: WOPRL = WOPR + L) and LGR-local (leading L:
LWWIR = L + WWIR) summary vectors are systematic variants that opm-common does
not enumerate. Recognise them when the stripped base is an indexed SUMMARY
vector, which keeps genuine typos flagged. Also extend the corpus harness report
with the full list of unique unrecognised keywords as an index-coverage worklist.

Cuts unrecognised-keyword false positives on the opm-tests corpus from 196 to
164.
opm-common defines only the base region-number keywords KRNUM and IMBNUM, so
real decks using the per-direction Cartesian forms (KRNUMX/Y/Z, IMBNUMX/Y/Z)
were flagged as unknown keywords. Emit the directional variants from the base
entry in the index build, and rebuild the bundled compact index.

Cuts unrecognised-keyword false positives on the opm-tests corpus from 164 to
134.
opm-common groups summary vectors into PROBE families (WELL_PROBE, FIELD_PROBE,
BLOCK_PROBE, …) that enumerate their concrete deck mnemonics in a deck_names
list (1691 unique) plus a deck_name_regex for open-ended families (UDQ, tracer,
water-cut). The build did not expand them, so real decks requesting vectors like
WWIP/WGIP/BTEMP/WXMF were flagged as unknown keywords.

- Build: expand each PROBE's deck_names into minimal recognised entries (name,
  sections, one-line summary; no size shape, so no arity/terminator checks), and
  emit the deck_name_regex families to data/summary_name_patterns.json.
- Diagnostics: computeDiagnostics takes the anchored summary-vector patterns and
  recognises matching tokens; the extension and corpus harness load and pass
  them. Also delivers the deck_names aliases groundwork (plan item 4).

Compact index grows to 3183 keywords (2647 KB, under the 3 MB budget). Cuts
unrecognised-keyword false positives on the opm-tests corpus from 134 to 34
(total 163 -> 63).
Emit opm-common's requires/prohibits constraints into the keyword index
and surface them as document-wide diagnostics: a 'X requires Y' warning
when a required keyword is absent (suppressed when the deck pulls in
INCLUDE files), and a 'X conflicts with Y' warning when a prohibited
partner is present. Implements plan item 1 of issue #6.
Validate each record value against the matching item's opm-common
value_type: flag a quoted string in an INT/DOUBLE slot and a decimal in
an INT slot. Bare identifiers (UDA/UDQ references) and defaults are left
alone, and the check is skipped for variadic-record table keywords.

The enum (options[]) mismatch check from the plan is deliberately not
implemented: the option sets are heuristically extracted from the manual
and are frequently incomplete/abbreviated (WCONINJE lists WAT, not the
valid WATER), which produced ~3000 false positives on the known-good
opm-tests corpus. Options stay in the index for completions only.

Also harden the item-1 requires check: suppress it for INCLUDE fragments
(no section header) and for phase requirements under implicit-phase modes
(CO2STORE/H2STORE), eliminating the remaining corpus false positives.
Implements plan item 2 of issue #6.
# Conflicts:
#	vscode-extension/src/analysis.ts
Two source files carried embedded NUL (0x00) bytes where a space delimiter
was intended inside template literals: the requires/prohibits pair key in
analysis.ts and the type+keyword corpus key in corpus.test.ts. The NULs made
git treat the files as binary. Replaced each NUL with a space; type-check and
the full jest suite (281 tests) pass unchanged.
The README's feature list and Unreleased release notes covered only the
boilerplate completion / quick-fix work; the value-type and requires/prohibits
diagnostics and the keyword-recognition / terminator relaxations added in this
branch were undocumented. Add a Diagnostics feature entry for each new check
and an Unreleased section summarising the user-facing changes.
@magnesj
magnesj merged commit d610100 into OPM:main Jun 29, 2026
4 checks passed
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