Nothing
NULL, TRUE, FALSE, NA and the @property
accessor are R, not JSON; a reader told "NULL = unweighted" who writes NULL
produces an invalid document. Say what the absent value means -- "Unset
leaves the cases unweighted" -- and leave the R spelling to the roxygen
@param.assert_description_language(): the contract's two prose rules on their
own. assert_config_contract() governs only what a caller-authored config
may demand, so records and results -- which publish prose too -- had no gate
at all.bounded_double_property() is removed; use prop_float(). It built a
bare new_property() with no spec, so prop_spec() returned NULL and its
bounds never reached the generated JSON Schema, leaving a class and its
published schema free to disagree. It also rendered infinite bounds closed
([0, Inf]) while rejecting infinities, never validated its own bounds, and
typed its value class_double, rejecting the integers jsonlite::fromJSON()
produces for whole numbers. prop_float() covers the same intervals via
min/max and exclusive_min/exclusive_max.check_bounded_double_scalar() and check_bounded_integer_scalar(), with
check_optional_* counterparts. Bounds are arguments rather than fixed in
the function name. The double check takes lower, upper, lower_open and
upper_open, mirroring prop_float(); the integer check takes inclusive
bounds. An infinite bound is reported and enforced open -- [0, Inf) -- so
the double check rejects Inf/-Inf like the property it mirrors. Both
validate their own bounds first, so an NA or inverted bound is a structured
rtemis error naming the bad bound rather than a base R comparison failure.assert_config_contract(), moved here from rtemis's data-raw/. The
schema registry has more than one producer, and only rtemis was holding
itself to the contract: rtemis.draw had been shipping chart/* documents
whose descriptions named R constructors, which nothing caught because the
gate lived in the other package's build script. Exported so both call the
same function; the rule predicates stay internal.setup_GLMNET." spends every reader's attention
on a function only one of them can call. Matched by construct, not taste:
setup_X, pkg::fn and .list_to_X are refused; prose naming a package --
"Elastic net (glmnet)" -- says what the algorithm is and stays.structural keeps its signature; only what it is expected to carry changed.write_JSONSchema() and write_lines(), moved here from rtemis. The
schema registry has more than one producer, so a document's shape belongs to
the registry rather than to whichever package emitted it. Keywords are
ordered on write; digits is an argument, I(17) where a double must
round-trip exactly.Imports are data.table
(MPL-2.0), S7 (MIT) and methods (part of R). The change unblocks
rtemis itself, which cannot be permissively licensed while it imports a
GPL package.html_tag() and the html_div(), html_p(),
html_span(), html_strong(), html_ul(), html_li() constructors, with
html_escape() and html_raw(). Elements are character strings rather
than a node tree, which is what fmt(output_type = "html") already emits and
what every consumer wants to embed or send over the wire. Text children are
escaped and markup children are not: a bare string is text, html_raw()
marks a string that is already markup, and the constructors mark what they
built. paste() drops that marker, so markup assembled with paste() is
passed on as html_raw(paste(...)). Output matches htmltools for the same
input, except that a child's own line breaks are indented with it, so
indentation always tracks nesting depth; HTML collapses that whitespace, so
the rendered result is identical. Packages that only built small fragments
of HTML can drop htmltools, and with it a GPL dependency.prop_boolean(), prop_integer(), prop_float(),
prop_string(), prop_bag() and prop_const(), with prop_spec() to read
a property's declaration back. One call carries the property's type,
default, bounds, enum, container and description, and its S7 validator is
generated from that declaration rather than written by hand. Because the
declaration stays attached to the property, prop_spec() can recover it
from a class definition to generate documentation, a JSON Schema, or a
defaults artifact. These succeed the hand-written properties in
R/03_S7_properties.R, which remain: prob_scalar is
prop_float(min = 0, max = 1) and optional_character_scalar is
prop_string(nullable = TRUE).get_output_type() can be overridden, so ANSI output is available in
non-interactive sessions (scripts, Rscript, the rtemis CLI's R
backend), which previously always resolved to "plain". With
output_type = NULL the resolution order is: filename (forces "plain"),
the new rtemis.output_type option, the new RTEMIS_OUTPUT_TYPE
environment variable, NO_COLOR (forces "plain"), then "ansi" when
interactive and "plain" otherwise. The option suits .Rprofile; the
environment variable lets a parent process decide per invocation.
Unrecognized values are ignored rather than raising, so a typo falls through
to the next rule instead of aborting a running job. The resolved type also
selects the progress display, so forcing "ansi" where output is captured to
a file yields carriage-return-rewritten lines, not just escape codes.repr_ls() shows an S7 element whose repr() is a single line on the
element's own line, like a value, rather than breaking to the next line.
The break exists so that every line of a multi-line repr() carries the
same pad, which a one-line repr() does not need; without this a one-line
repr() also had to end in its own newline or the following element ran on
after it. An element whose repr() fails is reported inline the same way.abort() gains a data argument: a named list of structured fields
attached to the signaled condition (e.g.
data = list(status_code = 429L, provider = "anthropic")), retrievable by
handlers via condition$<name>. Names may not collide with the built-in
condition fields (message, parent, call, trace).fmt() and all its wrappers, and the show_df()/show_table()/
repr_ls() printers, default to output_type = NULL, resolved via
get_output_type(): "ansi" in interactive sessions, "plain" otherwise.
Previously they defaulted to "ansi" unconditionally, emitting raw escape
codes in scripts, knitr and tests. Explicitly passing "ansi", "html" or
"plain" behaves as before; NULL can now be forwarded through the whole
formatting stack, so callers that only pass output_type through no longer
need to resolve it themselves.get_output_type() called with no arguments is environment-aware;
previously it returned "ansi" unconditionally because its default skipped
the NULL branch.output_type, so handles created with output_type = "plain" no longer
emit an ANSI-bold checkmark in interactive sessions.progress_update() validates label, current and add with the same
condition classes as progress_begin().R/progress.R), replacing the ecosystem's last
use of cli (cli::cli_progress_along): a progress_begin() /
progress_update() / progress_end() handle API plus progress_lapply(),
a near-drop-in wrapper with lapply-style X/FUN arguments so ...
forwarding never collides with the wrapper's own parameters.options(rtemis.progress_spinner = ): "dots", "dot", "blocks") and a
breadcrumb of all nested levels (Outer 2/5 > Tuning 7/30 ETA 0:41).
Non-interactive/plain output prints one begin and one completion line
instead. Redraws are throttled via options(rtemis.progress_throttle = ).set_msg_sink() envelope with level = "progress" and node fields
(node_id, parent_id, kind, status, current, total). Sink events
fire regardless of verbosity, which gates only the console renderer;
"update" events honor the throttle.Outer 2/2 x Tuning 24/24 done in 0:41),
recursively. A nested level is included only when all of its runs completed
fully with identical label and total; otherwise the chain is omitted rather
than misleading.msg()/msg0()/msgstart()/msgdone()/suggest() clear a visible
progress line before writing, so log output never collides with an
in-place redraw.progress_lapply() intercepts message()/warning() conditions from
user code and clears the status line before they print. Direct stdout
writes (cat(), print()) cannot be intercepted; new progress_clear()
is the escape hatch for those.msg()/msg0() now close a pending msgstart() line before writing, so
log lines and error stamps no longer collide with unfinished progress text
(new internal line_open state).pcat(): pad argument support.green is now teal; the previous green moved to new
juniper; added terracotta; adjusted light_mauve and success color.printls()/repr_ls() print class names single-quoted and use the primary
class only, for consistent object of class '...' output.msg() with custom sink support from rtemis: allows for logging through rtemis.server to rtemisliveheaddot() renamed to collapse_head()abort() dual-channel error signaler (in log.R): emits a styled
one-line event to the operator console (most-specific class name +
caller bracket) and signals a condition whose $message field is plain
text - safe to serialize into JSON/HTML/any ANSI-unaware sink.abort() captures the call stack at the signal site and attaches it to
the condition as $trace. Unlike base R's traceback() (which only
populates .Traceback for uncaught errors), $trace survives
tryCatch() and travels with the condition - useful for server-side
handlers that ship errors to a browser-side debug pane.format_trace() helper: renders the $trace pairlist (or
the condition itself) as a numbered, one-line-per-frame string.abort() resolves the user's calling function via a stack walk that
skips frames in this package and in base (tryCatch, doTryCatch,
etc.). Both the console bracket and the condition's $call field point
to the same user frame - so R's default error printer shows
Error in my_func(x) : ... instead of bare Error: ..., regardless
of how many check_* / clean_* wrappers sit between abort() and
the caller.info(), warn(), success(), dbg() log helpers, all routed
through msg() for consistent timestamp + glyph + caller-bracket
formatting.check_* / clean_* abort carries
failure-mode classes (rtemis_null_input, rtemis_na_input,
rtemis_type_error, rtemis_length_error, rtemis_range_error,
rtemis_value_error, rtemis_dependency_error), all inheriting from
rtemis_input_error - callers can catch input failures broadly or
narrow to a specific failure mode via tryCatch().rtemis.show_caller (default TRUE): set to FALSE
in .Rprofile to suppress the caller bracket on all log lines for the
session.format_caller() now auto-suppresses non-name expressions (anonymous
function literals, inline do.call-style invocations) - no more
[function (ws, req) {...] brackets cluttering logs from
callback-heavy code.check_* and clean_* functions now signal errors via abort()
with structured condition classes rather than via cli::cli_abort().
Error message text changes from cli's {.var x} styling to plain
backtick-quoted names (e.g. `x` cannot be NULL.). Code that
matches on exact error message strings will need to be updated.
Generic tryCatch(error = ...) handlers continue to work; handlers
keyed on the previous rlang_error / cli-specific classes will
need to be updated to the new rtemis_error hierarchy (which also
gains structured failure-mode subclasses).check_* function setAny scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.