| name | neqsim-professional-reporting |
| version | 1.0.0 |
| description | Engineering deliverable quality — the nine analytical-depth moves (contributor ranking, adjudicating the source document, quantitative rule-outs, robustness crossover, conservatism direction, discriminating test), results.json schema, figure→discussion→linked_results traceability, evidence matrices, assumptions/gaps registers, citation conventions, KaTeX math formatting, units consistency, executive-summary structure, AACE class declaration. USE WHEN: producing a task report, a PEPR/M1/root-cause problem-solving report, building a notebook deliverable, or finalizing any engineering output that needs to look like it came from a senior engineer. Consolidates the rules scattered across AGENTS.md and copilot-instructions.md. |
| last_verified | 2026-07-09 |
NeqSim Professional Reporting Skill
What separates "an answer" from a professional deliverable: traceability,
unit hygiene, citation discipline, structured results.json, and a report
narrative that matches the way senior engineers communicate.
When to Use
- Finalizing any task report under
task_solve/
- Building Jupyter notebook deliverables (study-grade, not exploratory)
- Producing FEED-quality memos, technical notes, or design basis documents
- Any output that will be read by a reviewer, client, or auditor
Principle 0 — Analytical depth (what makes a report worth reading)
Principles 1–10 are hygiene: they stop a report being wrong or unreadable.
They do not make it useful. A hygienic report that restates the originating
memo, lists contributors without ranking them, and ends in "further study is
recommended" passes every checklist below and tells the reader nothing they did
not already know.
The depth of a report is set in the study, not in the write-up. Plan for
these moves while the analysis is still running — most of them cannot be added
afterwards.
The nine depth moves
Aim for ≥ 6 of 9 on a Standard report and all 9 on a Comprehensive or
root-cause/problem-solving report. Record the score in results.json
(depth_score) and name the moves that were not achievable and why.
| # | Move | What it looks like | Anti-pattern it replaces |
|---|
| 1 | Rank the contributors on one common basis | A single table of every candidate cause with an improvement factor or utilisation number, computed the same way, so they are directly comparable | An unranked bullet list of "contributing factors" |
| 2 | Adjudicate the source document's own conclusions | A verdict table over each recommendation of the originating memo/PEPR/notification: Supported / Supported with a correction / Challenged, each with the number that decides it | Silently agreeing with the source, or silently ignoring it |
| 3 | Rule things out, quantitatively | "Thermal cycling does not explain this, by three orders of magnitude" — a competing explanation eliminated with a number and a stated margin | Leaving every hypothesis nominally alive |
| 4 | Find what the source document missed | A contributor, coupling, or second-order consequence absent from the originating document, established from evidence — and stated as such | Answering only the question as posed |
| 5 | Test the conclusion's robustness and say where it flips | A sensitivity table over the one or two genuinely uncertain modelling parameters, plus the explicit crossover point: "the top two swap around a slope of ~0.7, but the headline does not depend on it" | A single-point answer with an unquantified caveat |
| 6 | State the direction of every conservatism | Each screening value, default, and correlation labelled as an upper or lower bound on the reported quantity, so the reader knows which way the number can move | Undirected "this is approximate" |
| 7 | Name the cheapest discriminating test | The single measurement or inspection that would confirm or refute the diagnosis, why it discriminates, and what each outcome would mean | A generic "further investigation is recommended" |
| 8 | Report what does not fit | The observation that disagrees with the model, reported as a disagreement rather than smoothed over or omitted | Presenting only corroborating evidence |
| 9 | Convert qualitative asks into specifications | "Effective oxygen exclusion" → a purity table with the consequence of each grade; "improve filtration" → a micron rating with the mechanism that sets it |
Two further depth habits
- Look for the natural experiment in the data. Near-identical units with
different duty, a repaired section that failed again, a period with a barrier
out of service — these discriminate between hypotheses far more cheaply than
any model. Actively search the fleet/historian/maintenance record for one.
- Bound rather than assert. When a value cannot be measured, compute what it
would have to be for the conclusion to change ("the screening factor of 4.0
would require a shear ratio of 16; this geometry produces 2.74"). A bounded
unknown is a result; an asserted unknown is a gap.
Numerical results earn their own subsection
Any non-trivial computed result (CFD, FEM, transient, Monte Carlo, optimiser)
gets: validation against an analytical or independent value first, then a
convergence/mesh/sample-count check, then the result, then an explicit
statement of what the computation does and does not decide. A quantity that
still moves with refinement is an artefact and must be reported as one — report
the converged averaged measures, not the unconverged point maximum.
Report skeleton for a problem-solving / root-cause / PEPR report
Executive summary ranking table + the conclusion that inverts or
confirms the source document + N further findings
(count them; keep the count in sync)
0. Design/evidence basis what was retrieved, with document ids and revisions,
and the two or three basis facts that change the reading
1..n Findings one section per finding, each: observation (numbers) →
mechanism (physics) → implication (for the decision) →
recommendation (specific action)
n+1 Robustness sensitivity table + where the conclusion flips
n+2 Ruled out each eliminated hypothesis with its quantitative margin
n+3 Assessment of the verdict table over the source document's own
source's recommendations recommendations
n+4 What remains open per-finding, not one lumped register; each with the
test that would close it and its owner
Every section that reaches a conclusion ends with "what remains open" for
that conclusion specifically. One consolidated gap register at the end of a
report is where gaps go to be ignored.
Depth failure modes to check for before sending
| Symptom | What it means |
|---|
| The report's recommendations are the source document's recommendations | Moves 1–4 were not attempted |
| Every hypothesis is still "possible" | Move 3 was not attempted |
| The only number in the executive summary is a restatement of the input | The study produced description, not analysis |
| "Further study is recommended" with no named test | Move 7 was not attempted |
| No sentence in the report contradicts anything | Moves 2, 4, and 8 were not attempted — verify this is genuinely the case, not avoidance |
Principle 1 — Traceability Chain (MANDATORY)
Every figure → discussion → result must be linkable both ways:
results.json[key] ──→ discussed in §3.2 ──→ shown in figures/fig_03.png
↑ ↓
└──── caption references key ────────────┘
Required JSON schema fragment:
{
"figures": [
{
"id": "fig_03",
"path": "figures/fig_03_phase_envelope.png",
"caption": "Phase envelope at 95 mol% methane composition.",
"discussed_in": "section_3_2",
"linked_results": ["dew_point_T_K", "cricondentherm_K"]
}
],
"results": {
"dew_point_T_K": {"value": 244.3, "unit": "K", "source": "neqsim TPflash"},
"cricondentherm_K": {"value": 254.8,
Principle 2 — Executive Summary Structure
Every report opens with a 1-page executive summary built from these blocks (in order):
- Objective — one sentence: "Determine X for Y under Z conditions."
- Method — one sentence: "Using EOS / equipment model / standard X."
- Key result — 2–3 numbers with units and uncertainty (P10/P50/P90 if Monte Carlo run)
- Conclusion — one sentence with the engineering decision
- Limitations — 1–2 bullets on key caveats
The executive summary and problem description are report-blocking sections. Do
not leave template text such as "[Replace with ...]" or "[Auto-populated ...]"
in a final HTML/Word report. If results.json and task_spec.md contain enough
information, generate these sections automatically from those sources; otherwise
pause and fill the missing source material before finalizing.
Principle 3 — Units & Significant Figures
- State units everywhere —
bara, °C, kg/h, MJ/Sm³, never bare numbers
- Significant figures match accuracy — 3 sig fig for thermo; 2 for cost; never more than 4 unless source is exact
- Consistent within report — pick one set (SI, °C/bara) and don't switch
- Standard conditions — always disclaim Sm³ basis (15 °C / 1.01325 bara, or 20 °C, or 0 °C — they differ ~5%)
- Stream tables — use standardized columns: name, T [°C], P [bara], ṁ [kg/h], xi [mol%]
Principle 4 — Citations
For every standard, correlation, or vendor source:
Per **API 521 §5.15 (2020)**, fire heat input is Q = C × F × A_w^0.82 [API521-2020].
References:
[API521-2020] API Standard 521, Pressure-Relieving and Depressuring Systems, 7th ed., 2020.
[NORSOK-P-100] NORSOK Standard P-100, Process Systems, Rev. 3, 2018.
[Turton-5e] Turton et al., Analysis, Synthesis and Design of Chemical Processes, 5th ed., 2018.
Avoid: "as is well known", "industry standard says". State the source.
Principle 5 — Math (KaTeX)
For documents rendered through Jekyll docs site:
Inline: the acentric factor $\omega$ affects $\alpha(T_r, \omega)$.
Display:
$$
P = \frac{RT}{v - b} - \frac{a(T)}{v(v + b)}
$$
Never use \[ ... \] or \( ... \) — they are stripped by markdown processors.
Principle 6 — Figure Quality
Every plot must have:
- Axis labels with units —
Pressure [bara], not P
- Title — what is shown, at what conditions
- Legend — even with 1 series (states what is plotted)
- Grid — minor or major, increases readability
- Annotation of key values — pinch point, surge line, design point
- Resolution — ≥ 150 DPI for embedding, vector (SVG/PDF) preferred for line plots
fig, ax = plt.subplots(figsize=(8, 5), dpi=150)
ax.plot(T, P, label="Phase envelope")
ax.scatter([T_op], [P_op], color="red", marker="x", s=80, label="Operating point")
ax.set_xlabel("Temperature [K]")
ax.set_ylabel("Pressure [bara]")
ax.set_title("Phase envelope — sales gas, 95% C1")
ax.legend(loc="best", fontsize=9)
ax.grid(alpha=0.3)
fig.tight_layout()
fig.savefig("figures/fig_03_phase_envelope.png", dpi=150)
Principle 7 — Uncertainty Disclosure
Standard / Comprehensive task reports MUST include:
- Monte Carlo with P10 / P50 / P90 for any economic or reservoir-tied output
- Tornado diagram ranking inputs by impact on the key output
- Sensitivity scan to top-3 driving inputs
- AACE class declaration for any cost number (Class 5: ±100%, Class 4: ±50%, Class 3: ±30%)
Quick tasks may skip MC but still must state qualitative uncertainty.
uncertainty sub-schema (validated by the gate). p10, p50, p90 must be
numeric and monotonically ordered (p10 ≤ p50 ≤ p90); a non-numeric or
out-of-order percentile is a hard error in both TaskResultValidator and
devtools/validate_task_results.py. Include method and n_simulations
(≥ 200 when the Monte Carlo loop runs full NeqSim simulations).
The community skill neqsim-uncertainty-quantification emits this block
directly (UncertaintyReport.to_results_json()), in the correct ascending
convention, with the sampler and seed, the tornado, a convergence check, and a
blockers field. Note the trap it guards: p10 here is the 10th percentile
(the low estimate), the opposite of the petroleum resource convention where
P10 is the optimistic volume. State which convention a resource table uses.
Principle 8 — Risk Section
Standard / Comprehensive reports include a risk register scored on a 5×5 matrix
(probability × consequence) per ISO 31000 / NORSOK Z-013, with mitigation actions.
Use neqsim-process-safety classes.
Principle 9 — Benchmark Validation
Every numerical result must be benchmarked against an independent reference:
| Output | Benchmark |
|---|
| Phase envelope | Lab CME / CVD / GERG-2008 reference |
| Equipment cost | Vendor budget quote OR another correlation |
| Heat duty | Hand check: Q = ṁ × cp × ΔT |
| PSV size | Independent calc per API 520 worked example |
| NPV | Two methods: DCF and (NPV/CAPEX) ratio |
State the benchmark in the report. No benchmark = result is provisional.
benchmark_validation sub-schema (validated by the gate). Emit it as a JSON
array (or an object wrapping benchmarks/cases). Each entry must carry:
| Field | Purpose |
|---|
what / name / output / parameter | what was compared |
reference / source / benchmark / reference_value | the independent reference |
delta_pct / deviation_pct / status / neqsim_value | the comparison result |
status (optional) | one of PASS, FAIL, WARN, INFO (any other value is rejected) |
Both TaskResultValidator (Java) and devtools/validate_task_results.py (the CI
gate) now check this structure, so a malformed benchmark block fails the gate
instead of crashing the report generator.
The community skill neqsim-benchmark-reference-data emits this block directly
(BenchmarkReport.to_results_json()), together with the citation, the authority
tier of the reference, whether the deviation is inside the reference's own
uncertainty, and the three-graded-point check. Prefer it over hand-writing the
block with pasted reference literals.
Principle 9b — Evidence Matrix for Safety Studies
For safety-critical studies, especially trapped-liquid fire rupture, relief,
depressurization, MDMT, and consequence handoffs, include an evidence matrix and
assumptions/gaps register in both results.json and the report:
| Report item | Required content |
|---|
| Evidence matrix | Document id, title, revision, page/sheet, extracted value, unit, confidence, consuming calculation |
| Assumptions/gaps | Missing value, screening default used, impact on result, action to close, owner if known |
| Standards basis | Standard number/year, clause/table/equation, PASS/FAIL/INFO status |
| Segment summary | Segment id, limiting mode, event times, PFP margin, source-term handoff status |
| Recommendations | Specific action: relief/PFP/procedure/data retrieval/detailed specialist analysis |
Do not hide missing material certificates, flange/gasket/bolt ratings, fire-study
heat fluxes, or acceptance criteria. A study may still provide screening results,
but the executive summary must state when final design is blocked by evidence gaps.
Safety-critical reports must include a front-page readiness badge or equivalent
plain-text label: NOT_READY, SCREENING, or DESIGN_GRADE. The label must be
backed by visible blockers/findings and must not imply sign-off when any
controlled-document, historian/tagreader, pressure-profile, or material basis is
missing or unreviewed.
For script-backed studies, study_config.yaml is the source of truth for whether
notebooks are required. A report generator should not warn about missing planned
notebooks when the configuration explicitly says notebooks.required: false,
execution_required: false, and execution_engine: script.
Before report generation, check consistency between task_spec.md, analysis
scripts/notebooks, results.json, and the report narrative. Method changes such
as replacing a reconstructed depressurization profile with a directly exported
dynamic NeqSim profile must be reflected everywhere, including
capability_assessment.md, analysis.md, and neqsim_improvements.md when
workflow gaps were found.
Principle 10 — results.json Master Schema
{
"task_id": "2026-04-26_my-task-slug",
"task_type": "B-process",
"scale": "standard",
"objective": "...",
"method_summary": "...",
"agent_workflow_plan": {
"discovery": {"skill_search": "devtools/skill_search.py", "agent_search": "step1_scope_and_research/agent_plan.json"},
"agents_used": [ {"name": "...", "repo": "neqsim|community|enterprise", "role": "...", "loads_skills": ["..."]
... ... ...
Common Mistakes
| Mistake | Fix |
|---|
| "About 100 kg/hr" in a final report | State value with sig figs and uncertainty |
| Mixing barg / bara silently | One pressure basis per report; document conversion |
| Cost without escalation year | Always cite CEPCI year and Class of estimate |
| 6-decimal numbers from a simulator | Round to 3 sig fig; simulator precision ≠ result accuracy |
| Figure with no caption / no axis units | Reject — these are unread placeholders |
| "Standard says" without citation | Provide doc, year, section |
| No benchmark validation | Run hand check or compare to literature; report deviation % |
| Discussion that doesn't reference its figures | Use [fig_03] cross-references in prose |
Validation Checklist (RUN BEFORE FINALIZING)
Depth (Principle 0) — check these first; they cannot be fixed by editing prose:
Hygiene:
Pre-send review (the pass that catches stale numbers)
A report assembled incrementally accumulates contradictions: an early section
states a first-pass number, a later section supersedes it, and the early one
survives. consistency_checker.py does not catch these — they are internally
well-formed. Run this pass separately, immediately before sending.
1. Repeated-quantity sweep. Extract every quantity that appears more than
once and confirm the values agree:
import re, pathlib
t = pathlib.Path("step3_report/report.md").read_text(encoding="utf-8")
for q in ["boiling", "design flow", "margin"]:
for i, line in enumerate(t.splitlines(), 1):
if q in line.lower() and re.search(r"\d", line):
print(i, line.strip()[:120])
Anything quoted at two different values must be either reconciled or explicitly
labelled with its basis ("13.1 bar against the design pressure, 10.3 bar against
the measured pressure").
2. Numbered-list integrity. Lead-ins like "Three further findings:" drift out
of sync when items are added. Count the items.
3. Section numbering. List ^## headings and check for gaps — an §8 → §10
jump reads as a missing section to a reviewer.
4. Stale open/closed statuses. Every "Open", "not yet retrieved", "would be a
free test" in the limitations and next-actions sections must be re-read against
what the study actually ended up doing. Work performed late in a study routinely
closes gaps that the gap register still lists as open.
5. Alternative-basis values must be in results.json too. If the report
quotes a quantity on both a design and a measured basis, both belong in
results.json — otherwise provenance closure passes on the primary value while
the secondary one is unsourced.
Recurring physical-quantity trap. A T → P_saturation table row read as if
that temperature were the boiling point at the operating pressure. Invert the
curve at the operating pressure; do not quote the nearest row. The same trap
applies to any monotonic property table used backwards (dew point, hydrate
curve, wax appearance).
Related Skills