Changes in version 0.3.1.9000 - The package has a logo. - README carries status badges and lists related packages. - CI runs lintr (report-only) and test coverage. Changes in version 0.3.1 - Documentation names kernR's mechanism-consistency test directly. Changes in version 0.3.0 Grounding token - grounding_unverified() now returns "ungrounded"; the bracketed token of 0.2.0 and earlier is still accepted by combine_grounding(), decision() and valuation(). The tail will not price a quantity that is not an action - A manifest whose outputs columns are named something other than the candidate labels is now declined, classed outputs_not_action_indexed. Positional correspondence between outputs columns and candidates was an assumption the contract never stated. A gpfield spatial-prediction manifest carries x, y, z, mean, sd and n_support; against six candidate nitrogen rates the column count matched, and the tail returned a confident action built from a spatial coordinate and a posterior standard deviation. It now declines. Supply utility to say how a column is priced, or emit action-indexed outputs. - A structure manifest is declined by target, classed target_not_priceable, rather than waiting for a shape check to happen to catch it. A recovered causal graph is not a predictive quantity, and pricing one reads adjacency entries as action values. - The remaining two bare stop() calls in the tail -- a candidate/column shape mismatch and a single posterior column with no utility -- are now typed declines (candidate_shape_mismatch, utility_required), so every outcome of the tail is either a decision or something is_orchestra_decline() can read. - Found by a cross-member probe, not by this package's own suite: every manifest fixture here is shaped correctly by construction, so none of the three paths above could be reached from inside decideR. The workspace conformance suite now drives this tail with a real manifest from each of the eight fleet emitters. The manifest tail declines typed - A manifest this tail cannot price now raises a typed decline, classed decideR_abstention / orchestra_refusal, instead of a bare stop(). The fleet predicate is_orchestra_decline() reads the class, so an untyped error here defeated the refusal contract every other seam honours: a caller could not tell "the producer issued no number" from "decideR broke". A quorum verdict that reached no quorum is exactly the first case. - A failure in the caller's arguments is still an error. The distinction is deliberate: what the manifest carries is the producer's business and declines typed; what the caller passed is a programming mistake and must not be dressed as an abstention. Documentation - Getting started with decideR was brought to the orchestra's vignette quality bar: Why/What/Do/Read/Limits shape, every printed number computed inline, ggplot2 figures for the nitrogen-rate and grade-band decisions, and the grounding firewall read in prose on a decision that abstains for real. Changes in version 0.2.0 Fixes from the 2026-08-25 ORCHESTRA fitness audit. New features - decide_evpi() prices the expected value of perfect information over the same manifest, candidate set and utility the decision tail takes: E[max_a U(a, theta)] - max_a E[U(a, theta)] over the feasible candidates. It is the ceiling on what any study addressing the latent state could be worth. - decide_evsi() prices one named prospective sample -- this soil test, this trial, at this site -- by the standard two-loop pre-posterior algorithm, with the inner update obtained by importance re-weighting the manifest's own draws rather than by a nested re-fit, so the manifest remains the single source of the posterior and the package gains no sampler. The effective sample size of the weights is reported and warned about when it degenerates. - decide_bcr() discounts a benefit stream and a cost stream at an explicit rate over an explicit horizon and reports the components an impact assessment is written from: both streams, the present value of each, the net present value and the ratio, plus a posterior ratio summary when the benefit stream arrives as manifest draws. - bcr_crrdc(): CRRDC-guideline benefit-cost with mandatory counterfactual, attribution and adoption profile; closes the fleet-audit gap. It refuses -- with a message naming the unmet requirement -- to construct a ratio without an explicit counterfactual (a benefits-under-counterfactual stream, or a declared-already-net label), an explicit attribution share in (0, 1], or an adoption profile with lags covering every benefit year (never an implicit 100% uptake). The ratio is reported at the central discount rate and at the CRRDC sensitivity band side by side in a decider_bcr object's rates table, and an ungrounded input abstains -- with every rate's bcr/npv/pv_benefits/pv_costs NA -- rather than pricing a ratio a funding submission would quote. - valuation, a new S7 result class for all three. It carries the value beside its grounding token and its abstention record, so an ungrounded input prices out as a typed abstention with value = NA_real_ -- never a number a reader would spend money on. An abstained valuation is class-stamped decideR_abstention, so the federation's is_orchestra_decline() predicate recognises it without decideR depending on the contract layer. - A too-close-to-call decision (insufficient_evidence) does not block a value of information: it is exactly the situation in which information is worth buying, and the indecisive decision is returned in the valuation's @baseline. Bug fixes - The decisiveness gate no longer silently no-ops for a categorical candidate set or an off-grid numeric safe_action (D-01). .match_candidate() returning no numeric match now falls back to the per-draw argmax probability, so the gate stays live for every candidate shape instead of becoming inert -- previously decide()'s own safe_action = NULL default, and every list/categorical candidate set, disabled the check with no warning. - decide_input_rate() and decide_position_size() no longer silently discard constraint, safe_label, method, metadata, and inputs passed through ... (D-02). Both now harvest the documented ... names and stop loudly on an unrecognised one rather than accepting and dropping it. A caller constraint to decide_position_size() ANDs onto the hard drawdown guard rather than replacing it. - print.grade_band_value() now dispatches on an installed package. The S3 method was correctly registered in the package's own method table but never reached by print()'s ordinary S3 dispatch once S7::methods_register() had run (D-03) -- the package's headline loss primitive printed as a raw closure dump. .onLoad() now explicitly re-registers the method after S7::methods_register(). - decide() (and every reference decision routed through the shared core) now abstains with a new degenerate_utility reason instead of failing with an opaque base-R error when every feasible candidate's expected utility is NA/NaN (D-04). - decide_from_manifest() now accepts a manifest whose draws are a single posterior column (the shape a flexyBayes posterior arrives in), recycling it across every candidate when utility is supplied, rather than refusing with a column-count mismatch (D-06). - The roxygen @examples for decide_from_manifest() and decide_rate_from_manifest() now build a readable S7 stand-in and actually run the manifest-tail call, rather than wrapping it in \dontrun{} around an undefined variable (D-07). Documentation - Clarified that the low_ess abstention trigger is opt-in -- it never fires unless the caller supplies min_ess -- in decide()'s roxygen and the vignette's abstention table (D-05). - decide_position_size()'s max_drawdown is now documented as a hard one-period loss-quantile (value-at-risk) floor, not a multi-period peak-to-trough drawdown statistic, which the previous wording could be read to promise (D-09). - is_grounded()'s roxygen and the vignette's abstention section now state the correct downstream gate: is_grounded() alone is TRUE for a decision that abstained for no_feasible_action, low_ess, or insufficient_evidence, since none of those reasons downgrades the grounding label; a consumer that must also refuse an abstained decision gates on is_grounded(x) && !x@abstained (D-14). - Named the Kelly (1956) reference for decide_position_size()'s expected log-growth objective and fixed a grammatical ellipsis in decide_from_manifest()'s utility documentation. - _pkgdown.yml now groups the reference index into four named sections (Decisions, Manifest tail, Grounding, Loss) keyed to the existing @family tags, replacing the single undifferentiated catch-all list (D-17). - Copy-edited five grammar/sharpness issues in the getting-started vignette and the README (mass-noun agreement, an elliptical "act ... when you should", a subject-verb number mismatch, a trailing preposition, a missing "in which") (D-18). - The getting-started vignette now carries two figures -- the nitrogen-rate candidate ledger and the grade-band schedule with the chosen rate's protein posterior overlaid -- each with a caption and an interpreting sentence; the vignette previously shipped with no figures at all (D-13). - README.Rmd now knits with md_extensions: -smart, so the generated README.md uses plain ASCII -- throughout instead of pandoc's smart-typography en dashes (D-20); README.md re-knitted, which also fixes the stale example output that printed grade_band_value()'s return as a raw closure dump instead of the band table (the D-03 print-dispatch fix landed after the README was last knitted). Testing - Added a Suggests-guarded test that drives decide_rate_from_manifest() through a REAL orchestra_manifest built from the ORCHESTRA workspace's own reference contract (hash-verified), rather than only ever consuming a decideR-authored stand-in -- the Independent Oracle Principle gap the audit named (D-08). Skips cleanly when the workspace is not present alongside the package. Infrastructure - Replaced the R-CMD-check GitHub Actions workflow with the estate's known-green template (the previous workflow had never completed a real build in this repository's history) (D-10). - An abstained decision now carries an additional "decideR_abstention" class tag (recognised by the ORCHESTRA leader-node's cross-member is_orchestra_decline() predicate) alongside its existing S7 class, so a decideR abstention is identifiable at a cross-member seam without the consumer depending on decideR's namespace. Changes in version 0.1.0 First formal release. decideR is the decision layer of the ORCHESTRA analytics framework: the loss-optimal, grounding-aware closer of the inference-to-decision loop. It maps a posterior -- or an upstream member's orchestra_manifest inference result -- into an action under an explicit utility and a hard feasibility constraint, with calibrated abstention and an Independent Oracle Principle grounding firewall. This release adds the manifest-native pipeline tail and the grade-band loss primitive, and formalises the decision engine, grounding vocabulary, and reference decisions that the development series exercised. New features - Add a manifest-native pipeline tail. decide_from_manifest() turns an upstream orchestra_manifest into a decision by reading the predictive draws and the producer's grounding token straight off the manifest, then routing them through the same expected-utility engine decide() uses. The grounding rides from the producer through the decision, so an ungrounded payload forces an abstention at the pipeline boundary. decideR does not depend on the contract package: the manifest is read through its public S7 properties (outputs, metadata, summary), so the tail consumes any conforming producer rather than special-casing each one. - Add decide_rate_from_manifest(), the agronomic convenience that sources a yield-per-rate posterior and its grounding from a manifest and emits a profit-optimal nitrogen-rate decision -- the formalised crop-pipeline tail. - Add a grade-band (threshold-economics) loss primitive. grade_band_value() builds a step value schedule whose payoff jumps at quality breakpoints (a grain price that steps up as protein clears a milling and a premium threshold, say), and grade_band_utility() turns the schedule into a decide()-ready utility. Under a step payoff the optimal decision is governed by the posterior probability of clearing each band, not by the posterior mean. This is a building block for the future grainPlan orchestrator. Formalised in this release - decide() chooses the feasible action of greatest expected utility over posterior draws, abstaining to a safe action on any of four triggers -- un-grounded input, no feasible action, low effective sample size, or a move that is not clearly better than the status quo. - decide_input_rate() and decide_position_size() are two reference decisions -- a crop nitrogen rate chosen by expected profit, and a trading position size chosen by drawdown-capped expected log-growth -- that route through the same engine, demonstrating one decision layer across two domains. - decision is the S7 result class, carrying the chosen action, the candidate ledger, the grounding label, and the abstention record, with print() and is_grounded() methods. - grounding_grounded(), grounding_unverified(), and combine_grounding() are the canonical provenance vocabulary, hardcoded to match the ORCHESTRA federation's ungrounded / grounded tokens (worst-case combination: one un-grounded input taints the decision).