generate-bounds
GitHub为缺失或不确定变量生成低/基/高假设范围,支持确定性场景或蒙特卡洛模拟。适用于参数提取与验证后、计算生成前的阶段。
Trigger Scenarios
Install
npx skills add PlanExeOrg/PlanExe --skill generate-bounds -g -y
SKILL.md
Frontmatter
{
"name": "generate-bounds",
"description": "Use when the user wants to generate low\/base\/high assumption ranges (bounds) for missing or uncertain variables in a validated extract-parameters-from-full JSON, in preparation for deterministic scenarios or Monte Carlo"
}
Generate Bounds for Extracted Parameters
Overview
Wraps the bounds-estimator system prompt at system-prompt.txt (next to this file) and applies it to a parameter JSON produced by extract-parameters-from-full (and ideally already passed validate-parameters). Output is a strict JSON object keyed by variable id, with low / base / high / unit / rationale / source for every variable that needs an assumption range.
Stage 4 of the pipeline described in planexe_simulator/README.md.
When to Use
- User asks to "generate bounds", "estimate ranges", "add low/base/high", or "prepare for scenarios" given an extract-parameters-from-full JSON
- User wants to fill in assumptions for
missing_values_to_estimateand uncertainkey_valuesbefore running deterministic scenarios or Monte Carlo - Pipeline step between
validate-parameters(passes clean) andgenerate-calculations/run-scenarios
Not for: regenerating the parameter JSON (use extract-parameters-from-full), validating the JSON (use validate-parameters), or producing Python code (use generate-calculations).
Workflow
- Get the input JSON path. If the user did not provide one, ask. Do not guess.
- Read
system-prompt.txt(sibling of this SKILL.md). Its selection rules and spread heuristics are authoritative. - Read the parameter JSON. Assume it has already passed
validate-parameters; if it visibly hasn't, tell the user and offer to validate first. - Produce the bounds JSON per the system prompt.
- Self-audit before output. For each bound entry, verify:
- Every numbered citation in
rationale(Risk N, Issue N, Decision N) refers to content that substantively supports the claim — not just lexically present. - For variables feeding a declared gate threshold, the base-vs-threshold relationship is consistent with the rationale. If base implies base-case gate failure, the rationale names a report-internal anchor that justifies the shift.
source: "data"entries name an explicit anchor in the rationale.- For asymmetric bounds, the rationale notes the asymmetry's source. If any check fails, revise the bound; do not ship inconsistent state.
- Every numbered citation in
- Output destination. Default: print the JSON to chat. If the user asks for a file, write to the path they specify. Suggested default file path:
<input-basename>.bounds.jsonnext to the input.
Selection Rules (re-stated for emphasis — see system prompt for full detail)
Generate one bounds entry for every id that meets ANY of:
- it appears in
missing_values_to_estimate - it is a
key_valuewithvalue_type ∈ {inferred, missing_but_needed} - it is a
key_valuewithvalue == null - it is a
key_valuewithuncertainty == high - it is a
key_valuewithuncertainty == mediumANDmodelling_priority ∈ {critical, high}
Skip: explicit/derived key_values with low uncertainty, derived_questions, recommended_first_calculations, and formula LHS-only outputs that are not declared as inputs.
Spread by Uncertainty
| Uncertainty | Spread around base |
|---|---|
| low | ±10–20% |
| medium | ±25–50% |
| high | ≥±50%, up to a 2–5× factor when genuinely speculative |
Always low ≤ base ≤ high. Fractions stay in [0, 1]. Counts of discrete things (people, kits, centers, months) use integer bounds.
Output Shape
{
"<variable_id>": {
"unit": "fraction",
"low": 0.10,
"base": 0.20,
"high": 0.30,
"rationale": "Short, ≤50 words. Include required disclosures when applicable.",
"source": "data" | "assumption",
"sampling_discipline": "fraction",
"non_negative": true,
"default_pass_probability": null
}
}
Top-level is a single object keyed by variable id. Order keys roughly by importance (critical → high → medium → remaining missing values). Use "source": "data" only when the range is anchored in a citable real-world reference for similar programs; otherwise "assumption".
Sampling-discipline tag
Each entry MUST carry a sampling_discipline chosen by the LLM based on the variable's nature. Downstream consumers (run-scenarios, monte-carlo runner) read this tag directly and do not pattern-match on unit strings — so the LLM is the single authority for this classification.
| Value | Meaning | Downstream behavior |
|---|---|---|
"fixed" |
low == base == high; genuinely pinned |
Always return that value |
"bernoulli_gate" |
Binary pass/fail (staged funding, permit toggle, regulatory pass, conditional release). Requires default_pass_probability ∈ [0, 1] |
Bernoulli draw; low on fail, high on pass |
"integer" |
Countable units — people, households, sites, kits, days, … | Sample continuously, round, re-clamp to [low, high] |
"fraction" |
Bounded fraction in [0, 1] |
Clamp draws to [0, 1] |
"continuous" |
Real-valued; no rounding, no extra clamping beyond [low, high] |
Plain triangular/uniform draw |
non_negative is independent of discipline: set true when the variable cannot legitimately go below zero (continuous monetary amounts, counts, capacities); set false only when negative values are physically meaningful (a delta or net change variable).
default_pass_probability is required (a number in [0, 1]) when sampling_discipline == "bernoulli_gate" and MUST be null for every other discipline.
If no variable needs bounds, return {}.
Common Mistakes
| Mistake | Fix |
|---|---|
| Bounding every variable, including known explicit facts | Skip explicit/derived key_values with low uncertainty — they are facts, not assumptions |
Returning low == base == high for variables with real uncertainty |
Give a real range; identical bounds are only for genuinely pinned KPI commitments |
Wrapping output in ```json fences |
Raw JSON only |
Including derived_questions or recommended_first_calculations ids |
Those are outputs/questions, not bounded inputs |
| Inventing ids that are not declared in the parameter JSON | Every key must correspond to a declared id in key_values or missing_values_to_estimate |
Picking fractions outside [0, 1] (e.g. base 1.5 for a rate) |
Clamp to the unit's natural range |
Ignoring the parameter's uncertainty and giving everything the same ±20% spread |
Anchor the spread on the parameter's stated uncertainty level |
| Rationale cites a numbered artifact (Risk N, Issue N, Decision N) that does not substantively support the claim | Re-read the cited artifact. The number must match content, not just exist in the report. If you cannot find a substantively correct citation, drop the citation and mark source: "assumption". |
Shifting actual_X base past the X_target threshold without a report-internal anchor |
Center base at the committed value unless a named Risk / Issue / Decision / premortem / expert-criticism passage forecasts a gap between commitment and reality. "Realistic execution" and "operational drift" are not anchors. |
Generating bounds for a threshold or target variable (ids ending in _threshold, _target, _ceiling, _floor, _limit) |
Thresholds enter the simulation as their stated single value. Randomising them silently changes what pass_rate measures and breaks the threshold_basis = report_explicit contract. Skip these variables. |
Triangular bounds with base = high = target on a >= target gate variable (ring-fenced reserve, segregated escrow, allocation share, KPI floor that physically cannot overshoot) |
The continuous triangular CDF has zero probability mass at the exact peak — the >= 0 margin gate fails ~100% of runs even when the commitment is intact. The Critical verdict you report is a property of the bound shape, not the plan. Switch to sampling_discipline: "bernoulli_gate" with low = shortfall floor (e.g. 0 or partial-segregation amount), high = the target, and default_pass_probability = realistic execution probability of the commitment (e.g. 0.95 for a signed escrow, 0.75 for a sponsor-committed reserve, 0.5 for a contested allocation). Bernoulli returns high on pass and low on fail, so the gate cleanly tests whether the commitment was executed. |
Reference
- System prompt (authoritative):
system-prompt.txt - Pipeline overview and "what needs bounds" list:
../../README.md, Stage 4 - Companion skills:
../extract-parameters-from-full/SKILL.md,../validate-parameters/SKILL.md - Example input for testing:
/tmp/extract-params-heatwave-v8.json(passes validate-parameters withvalid: true)
Version History
- 846f612 Current 2026-08-20 11:18


