Skip to content

Add the note severity and a user-facing sentence for every diagnostic - #193

Merged
luisleo526 merged 13 commits into
mainfrom
win-diagnostic-final-tidy1
Oct 9, 2026
Merged

luisleo526 merged 13 commits into
mainfrom
win-diagnostic-final-tidy1

Conversation

@luisleo526

Copy link
Copy Markdown
Contributor

What this adds

Diagnostics only. No analyzer or code-generation file changes, and the C++ the transpiler emits is byte-identical for every corpus script.

  • note, a third diagnostic severity. A diagnostic is now an error, a warning or a note. A note is nonfatal like a warning: a script that produces only notes still returns ok: true and its C++.
  • Eleven advisory diagnostics become notes (PF-W1505, PF-W1508, PF-W1509 and PF-W1525 to PF-W1532). They describe things a backtest simply does not do or need (a display-only call, an informational reminder), not things a user must fix. Their codes are unchanged; only the severity moves.
  • user_message on every catalog entry (629 codes). A short, self-contained sentence a product can show to an end user, written as a template with named arguments. The existing message, explanation and hint fields are unchanged.
  • A written public contract for the three severities, the note migration, the template form and what a consumer may rely on (docs/PUBLIC_CONTRACT.md), with a migration call-out in the changelog.

Compatibility

A consumer that treats every severity other than warning as an error will show the eleven notes as errors until it handles note; the changelog's migration section says so. The catalog's set of codes and their order are unchanged. Package version and dependencies are unchanged; the changelog entry is filed under the planned 1.5.0, still unreleased.

Evidence

  • Test suite: 9,409 passed and 10 known skips over 9,419 cases; the 153 diagnostic-note cases re-run on this exact head.
  • Corpus: 314 scripts compile; emitted sources identical to the base for all of them.
  • Gate: 279 fixtures (266 expected successes, 13 expected errors), native and WebAssembly builds agree.
  • Parity gate over the whole measured population: PASS, no improvement and no regression (7,989 trade sets compared, none changed).
  • Two independent reviews of the final change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ko17oHtRco8iZ9vJptBAj8

luisleo526 and others added 13 commits October 9, 2026 01:27
The 97 switch-arm warning twins (PF-W1001..PF-W1097) carried their error
twin's user_message word for word, so 29 of them told a user that a call
PineForge had just accepted "is refused" (request.seed in a non-default
switch arm is PF-W1027, a warning with the na fallback kept), and the
nine "TradingView rejects" ones never said PineForge only warns.

- catalog: rewrite user_message of all 97 twins. Ninety-one say what the
  limitation is and that "In a switch arm PineForge only warns and keeps the
  arm's lowering" (the catalog's own explanation of the twin); the six
  DIVERGENT_VARS warnings (PF-W1067..PF-W1072) are warnings everywhere and
  name no switch arm. PF-E6062 now says it is array and matrix history inside
  request.security (collection_history.py), not user-defined type or drawing
  references (that is PF-E3043). Only user_message text changes: entry and
  field order, message, hint, explanation, args, severity and the pin digests
  are byte for byte as before.
- tests/test_diagnostic_notes.py: one case per twin (own sentence, no refusal
  wording, the switch-arm clause exactly where the twin's explanation has it),
  a no-refusal check over every nonfatal sentence with a detector table and
  mutation controls, a real accepted-arm interface case (request.seed ->
  PF-W1027, text constant -> PF-W1078: transpile succeeds, warning level,
  glue envelope carries the sentence), the same call outside an arm keeping
  the error sentence, and PF-E6062 on the request_security_size shape.
- tests/test_diagnostic_codes.py: restore (severity == "error") == (code[3] == "E").

New tests are authored, not run (phase limit); the final Spot proof runs them.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…call-out

PUBLIC_CONTRACT.md: replace the claim that visual-only and display-only
diagnostics are informational with the exact set of eleven codes that
migrate from warning to note, and name PF-W1502, PF-W1506, PF-W1507,
PF-W1078 and PF-W1552 as warnings that remain. Replace the stale "does
not return nonfatal warnings" statement with the error, warning and note
levels, read from the declared severity and never from the PF-E/PF-W
prefix. State that PF-W1505 stays a static note with no per-call
condition or suppression and that no sidecar exists yet, and that the
code pin does not cover user_message (only the eleven migrated templates
are fixed, by delta.json). Mark the note severity and user_message
additions "since 1.5.0".

CHANGELOG.md: add an Unreleased 1.5.0 entry with the consumer migration
call-out: note is nonfatal, user_message is a raw ICU template over args,
the exact migrated-code set, the stable legacy fields, and the warmup
sidecar as later work. No release date; VERSION, package manifests and
dependencies are unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
README, CLAUDE.md and AGENTS.md still said nonfatal diagnostics are
warnings only. Name the note level where they describe what
transpile_full() and the JSON envelopes return, read severity from the
declared level instead of the PF-E/PF-W prefix, show user_message in the
catalog entry example, and call the ta.ema warmup caveat, the visual-only
skip and the display-only request lowering notes. Only PF-W1505,
PF-W1508, PF-W1509 and PF-W1525 to PF-W1532 are notes; the other
visual-only and display-only diagnostics stay warnings. No runtime warmup
sidecar or conditional suppression is claimed.

Rename tests/test_external_requests.py::test_inert_requests_are_lowered_with_a_warning
to test_inert_requests_are_lowered_with_a_note. Body, assertions and
everything else in the file are unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The note for a call PineForge skips said "{name} is not drawn in
backtests.", which is wrong for alert() and alertcondition(): they draw
nothing on a chart. The sentence is now "{name}() does nothing in a
backtest." (PF-W1509: "{full}() does nothing in a backtest."), which holds
for every call the note covers. `name` is the call's bare or dotted name,
so the template's "()" is the only pair of parentheses a rendered
sentence has.

Only the two user_message templates change. Severity, message, hint, args,
explanation, codes and the pin are untouched, and the executable product
files are the parent's. The delta fixture, the receiver vector and the two
doc examples quote the same text. New tests drive alert, alertcondition,
plot and table.new through transpile_full and the glue, and compare the
generated C++ and every other diagnostic field with the parent head's.

The new tests have not been run; they run on Spot.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The four cases of
test_the_sentence_is_the_only_change_to_the_parent_heads_output
transpiled alert, alertcondition, plot and table.new with commit 5a252e7
and compared the C++ and every diagnostic field with that head's. The
commit is an intermediate one that a squash landing does not keep, so
reference_codegen() would have nothing to archive and the cases would
fail on main. They go with NO_EFFECT_PARENT, the _but helper and the _e2e
import, which only they used. The four real-call tests, the alias test and
the comparison of the interface cases with the pre-migration output stay.
The notes tests collect 153 cases instead of 157, so the whole collection
is expected to be 9419 instead of 9423 with the same ten known skips;
those counts are static expectations, not a run.

PUBLIC_CONTRACT.md and CHANGELOG.md said that the template of every code
but the eleven migrated ones is checked for form, not for wording. The
tests check more, and both now say what: delta.json fixes the eleven
strings, every template is checked for form, each of the 97 warning twins
has a sentence of its own that says PineForge warns (the 91 that warn only
in a switch arm also say the arm keeps its lowering), and no warning or
note template says PineForge refuses or rejects something, though one may
say what TradingView does. Other exact wording is not pinned.

README.md gets the contract's caveat: text that says "since 1.5.0"
describes the source tree on main, 1.5.0 is the planned next release, and
the statements about 1.4.0 keep their historical meaning.

Only these four files change; the catalog, the product code, the
fixtures, the pins, VERSION and the package inputs are the parent's. No
test was run for this commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@luisleo526
luisleo526 merged commit 6c8eadb into main Oct 9, 2026
8 checks passed
@luisleo526
luisleo526 deleted the win-diagnostic-final-tidy1 branch October 9, 2026 09:54
luisleo526 added a commit that referenced this pull request Oct 9, 2026
* docs: state the report-ownership contract for the paired engine fix

Add "A report belongs to the call that returned it" to the public contract,
a pointer in the README's run section and an Unreleased changelog note.

A call the engine refuses without beginning gets the empty report, never an
earlier run's rows; a run that began and then failed keeps its partial rows;
the explicit stream snapshot keeps the owner's rows; recorded outputs keep
their own record of the last run that began. Callers read the error text, the
error code and the run status, because a refusal before the engine admits the
begin leaves the status at its earlier value. A batch or reentrant begin over a
live stream latches Failed and a repeated stream begin does not; a configure
time calendar failure leaves the run-number high-water where a failure inside
the begin has already moved it.

The text is framed as the contract of an engine fix that is not yet released:
it names no release number and states that engine v1.4.0 does not carry it.
Markdown only; no source, fixture, version, lock or workflow file changes.

Rebased onto main 6c8eadb (#193), which added the 1.5.0 diagnostic notes. The
changelog note now sits under its own "Planned 1.4.0-line patch — Unreleased"
heading after main's unchanged "1.5.0 — Unreleased" section, and its opening is
scoped to this documentation change: it adds no Python, JSON, diagnostic or
emitted-C++ change, keeps the 1.5.0 diagnostics separate and names no tag, date
or version. The contract's availability paragraph now says the report fix
itself changes neither the generated C++ nor the transpiler's Python and JSON
contract, so it does not contradict the "since 1.5.0" text beside it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* docs: move the planned patch notes under 1.5.0

The report-ownership notes were drafted as a planned 1.4.0-line patch. The
paired engine's report fix is planned for 1.5.0, so the notes now sit in a
Documentation subsection of the 1.5.0 entry, and the entry's opening names that
scope. The codegen change stays diagnostics only. Only CHANGELOG.md changes:
README.md and docs/PUBLIC_CONTRACT.md are byte-identical to the reviewed commit
531755a.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
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