Skip to content

Sense 19: The Simulation

Sense 19 · Steady · Last touched 2026-08-20

  • last_verified: 2026-07-27

Synced from docs/design/sense_19_the_simulation.md in the engine repo — that’s the source; this page is a build-time mirror.

Don’t guess. Model it.

If the suggestion is concrete enough to describe as an intervention, and the intervention is deterministic enough to apply to data, then you can build the future before you live it.

Status: proposed Author: the owner + Claude (inspire walkthrough, 2026-04-17)


jinflow tells you what’s wrong (Signals), asks whether it’s real (Theses), explains why (Verdicts), and frames it strategically (Observations + Explanations + Contributing Factors). It even suggests what to do (Suggestions).

But then it stops. The user is left with a recommendation and a leap of faith. “Tighten the revenue leakage threshold to 5%” — okay, but what happens if we do? How many new findings? What’s the exposure delta? Does it break something downstream?

Today the only way to answer is to manually edit the AFS, rebuild, and compare. That works — jin make is a pure function, the AFS is branchable, the Diff Loupe exists. But it’s a developer workflow, not a product experience.

Four new terms complete the jinflow Experience from observation to action:

A human-readable recommendation for improvement. Any kind — process change, system fix, data cleanup, threshold adjustment, structural reorganisation. Not tied to a specific signal type or technical mechanism. A Suggestion is what to do.

suggestion_id: sug_tighten_revenue_leakage
category: threshold
target: signal_revenue_leakage
description:
en: "Tighten the revenue leakage threshold from 10% to 5%."
priority: high
origin: verdict_billing_workflow_gap # where this came from

Suggestions can originate from:

  • Verdicts — the root-cause analysis recommends an action
  • Subject Matter — an expert notes a known workaround
  • Observations — the strategic review identifies an opportunity
  • Human judgment — the analyst writes one from scratch

A deterministic, executable parameter change. The technical realisation of a Suggestion. An Intervention is precise enough that a machine can apply it to the AFS without ambiguity.

intervention_id: int_set_threshold_005
suggestion_id: sug_tighten_revenue_leakage
type: yaml_edit
target_file: signals/signal_revenue_leakage.yaml
changes:
- path: threshold
from: 0.10
to: 0.05
deterministic: true
reversible: true

Intervention types (initial set):

  • yaml_edit — change a value in a YAML artifact
  • artifact_add — add a new signal/thesis/verdict/smebit
  • artifact_remove — remove an instrument
  • config_change — modify tenant config
  • seed_edit — modify a seed CSV (e.g., update a reference table)

An Intervention is how to do it — concrete, diffable, auditable.

Reality + Interventions = Scenario. A Scenario is a named, branchable alternative state of the AFS with one or more Interventions applied.

scenario_id: scn_tighter_leakage
description:
en: "What if we tighten revenue leakage to 5%?"
base: main # the branch this scenario diverges from
interventions:
- int_set_threshold_005
status: draft # draft → built → compared → adopted | archived

A Scenario IS an AFS branch. The branch name is the scenario_id: scenario/scn_tighter_leakage. This aligns with the existing branching model in docs/design/afs_artifact_store.md.

Build the Scenario branch, compare the output KLS to production, and present the delta. A Simulation is the act of running jin make on the scenario branch and showing what changed.

The simulation output:

  • Finding delta — new findings, removed findings, severity changes
  • Exposure delta — CHF at risk: production vs. scenario
  • Thesis verdict changes — did any thesis flip from plausible to confirmed (or vice versa)?
  • Entity health delta — perspective scores before/after
  • Signal coverage — new signals added, old signals removed

Presented in the Diff Loupe (already exists for snapshot comparison) or a dedicated Simulation Results view.

Signal → Finding → Perspective → Thesis → Verdict
→ Observation → Explanation → Contributing Factor
→ Suggestion → Intervention → Scenario → Simulation

Or, in the language of the user:

StepQuestionAnswer
SignalWhat patterns exist in the data?Findings
ThesisIs this pattern real?Verdict (confirmed / plausible)
ObservationWhat does this mean strategically?Signed claim
ExplanationHow is it manifested?Evidence + hypothesis
Contributing FactorWhat composes the explanation?Structured causes
SuggestionWhat should we do?Recommendation
InterventionHow exactly?Deterministic parameter change
ScenarioWhat would the world look like?Reality + interventions
SimulationWhat happens?Build, compare, decide

jinflow’s architecture was built for this without knowing it:

  1. make is a pure function. AFS in → KLS out. No side effects. A scenario build produces an independent KLS with full fidelity.
  2. The AFS is branchable. Git branches are free. A scenario IS a branch. Merging a scenario IS adopting the intervention.
  3. The Diff Loupe exists. Snapshot comparison already works. Scenario comparison is the same mechanism with a different label.
  4. Interventions are YAML edits. The AFS is declarative. A threshold change is a one-line YAML diff. No code, no migration, no deploy.
  5. KLS is self-describing. The scenario KLS carries its own AFS archive (_jinflow_afs_archive), so the interventions that produced it travel with the result.

The user reads a confirmed Verdict: “The cause is a process gap between OR completion and billing entry.” Below the verdict, a Suggestions section lists actionable recommendations. The user clicks “What if?“

A lightweight editor shows:

  • The Suggestion’s proposed Intervention(s)
  • A preview of the YAML diff (what changes, old → new)
  • A “Build Scenario” button

jin make --scenario scn_tighter_leakage runs in the background. Progress bar in JinDesk. The user can continue browsing while it builds. When done, a notification: “Scenario ready — view results.”

4. Compare (Diff Loupe / Simulation Results)

Section titled “4. Compare (Diff Loupe / Simulation Results)”

Side-by-side: production KLS vs. scenario KLS.

  • Finding delta table (new / removed / changed severity)
  • Exposure bar chart (CHF production vs. scenario)
  • Thesis verdict flip table
  • Entity health heatmap delta

The user reviews the simulation and either:

  • Adopts — merge the scenario branch into main. The intervention becomes production on the next jin make.
  • Archives — keep the scenario for reference but don’t merge.
  • Iterates — adjust the intervention and re-simulate.

Phase 1 — Suggestion + Intervention (YAML artifacts) [shipped 2026-05-22]

Section titled “Phase 1 — Suggestion + Intervention (YAML artifacts) [shipped 2026-05-22]”

New instrument types: suggestions/*.yaml and interventions/*.yaml. Contracts at contracts/suggestion_contract.v1.json and contracts/intervention_contract.v1.json. Validators at scripts/suggestioncheck.py and scripts/interventioncheck.py.

Tier split. Suggestions are A-tier — they live on the suggestions orphan branch alongside notes / bookmarks / recents / bell, shared across every scenario. Interventions are B-tier — branch-bound (main + each scenario carries its own intervention set), because different scenarios are defined by different interventions.

Bake. bake_suggestion_registry and bake_intervention_registry in jinflow/cli/commands/baking.py read the AFS YAMLs and write _<tenant>.suggestion_registry + _<tenant>.intervention_registry to the KLS at every jin make. Hooked into all three make paths (metadata-only rebake, incremental, full clean).

Forward/reverse refs. A Suggestion declares interventions: [...]; an Intervention declares suggestion_id. Both directions land in the registries so JinDesk can navigate either way.

Safety. The Intervention checker rejects absolute paths in target_file and any path containing .. segments — defense in depth before Phase 2’s apply step ever touches the filesystem. Only deterministic: true interventions will be applied (Phase 1 emits a warning otherwise; Phase 2 will refuse).

What Phase 1 does NOT do: actually apply interventions. Phase 1 makes them addressable, validatable, queryable, durably stored, shared across scenarios. The apply step lives in Phase 2 alongside jin scenario create.

Phase 2 — Scenario Builder [shipped 2026-05-22]

Section titled “Phase 2 — Scenario Builder [shipped 2026-05-22]”

AFS branching via jin scenario create. Applies interventions to the branch deterministically; commits the result. CLI-first, JinDesk later. Building the scenario KLS uses ordinary jin make — scenarios are normal git branches.

Verbs:

Terminal window
jin scenario create <id> int_X [int_Y …] [--base BRANCH] [--tenant pack.tenant]
jin scenario list

Implementation:

  • jinflow/scenarios/apply.pyapply_intervention(afs_root, intervention_doc) does one deterministic yaml_edit. Uses ruamel.yaml for round-trip preservation: comments, key order, and quoting in the target YAML survive untouched, so the scenario branch’s diff against base is exactly the bytes the intervention changes. Refuses non-yaml_edit types, refuses to create missing keys, refuses absolute / ..-escaping target_file.
  • jinflow/scenarios/create.pycreate_scenario(afs_root, scenario_id, intervention_ids, base_branch=...) orchestrates the full flow: refuses dirty working tree, refuses pre-existing branches, creates scenario/<id> off the base, applies interventions in declared order, commits with a structured message. Rolls back the branch on any apply failure — half-applied scenarios are never left behind.
  • jinflow/cli/commands/scenario.pycmd_scenario_create, cmd_scenario_list. The CLI surfaces are thin wrappers over the package.

Drift semantics: each change carries a from value the intervention expects to find at the path. If the actual value differs, the apply refuses. Stacked interventions on the same path see the post-previous-intervention state, because applies run sequentially against the working tree (not against a pre-computed in-memory copy). Authoring two interventions where int_b.from is int_a.to works correctly.

What Phase 2 does NOT do: build the scenario KLS automatically. The user runs jin make <tenant> against the scenario branch when they’re ready. This keeps the verb surface small and aligns with the established “make is the build” convention.

Phase 3 — Simulation Results [shipped 2026-05-22]

Section titled “Phase 3 — Simulation Results [shipped 2026-05-22]”

Two new verbs that turn the Phase 2 scenario branch into a buildable, inspectable artifact:

Terminal window
jin scenario build <id> [--tenant pack.tenant]
jin scenario list # now shows BUILT yes/no per row

Where the scenario KLS lives. The existing jin make --branch infrastructure routes branch builds to a branch-named KLS file: <pack>_<tenant>_<safe_branch>_kls.duckdb in the store dir. For a scenario branch named scenario/lower_thresholds that resolves to <pack>_<tenant>_scenario_lower_thresholds_kls.duckdb — coexisting with the production working KLS at <pack>_<tenant>_kls.duckdb. The Compare route picks both up automatically; no new infrastructure was needed there.

jin scenario build is a thin wrapper over jin make --branch scenario/<id>. It exists for ergonomics and to catch missing-branch errors early (clearer message than what jin make would surface). The convention for KLS placement lives in one place: _scenario_kls_path in jinflow/cli/commands/scenario.py, which must stay in sync with the safe_branch logic in make.py. The test test_scenario_kls_path_convention pins both.

jin scenario list now annotates each scenario row with its build status, derived from KLS-file presence at the conventional path. So a typical flow surfaces clearly:

$ jin scenario list
BRANCH CREATED BUILT SUBJECT
scenario/lower_thresholds 2026-05-22 yes scenario: lower_thresholds
scenario/tighter_or_documentation 2026-05-22 no scenario: tighter_or_documentation

The Compare route’s existing snapshot-comparison machinery — already present in explorer/src/routes/[tenant]/compare/ — reads every *_kls.duckdb in the store and lets the user pick two sides to diff. Scenario KLSes show up there with their full filename (e.g., numetrix_rmc_scenario_lower_thresholds_kls.duckdb). The finding/exposure/thesis deltas, entity-health heatmap, and side-by- side rendering ALL already exist. Phase 3 didn’t need to touch the JinDesk — the Phase 2 KLS-naming-convention plus Phase 3’s documentation closed the loop.

What Phase 3 does NOT do: auto-label scenario KLSes distinctly from snapshot KLSes in the Compare UI (today they’re both *_kls.duckdb in the same list). That landed in Phase 4 (next section).

Phase 4 — Compare UI scenario mode [shipped 2026-05-22]

Section titled “Phase 4 — Compare UI scenario mode [shipped 2026-05-22]”

Three additions that make scenarios self-describing in JinDesk:

1. Scenario metadata bake. A new bake_scenario_metadata(kls_path, tenant_id, afs_root) runs at the end of every jin make and detects whether the current AFS branch is scenario/<id>. If yes, it parses the structured commit message that create_scenario wrote (with base branch and intervention list) and writes a row to _<tenant>.scenario_metadata:

CREATE TABLE _<tenant>.scenario_metadata (
scenario_id VARCHAR PRIMARY KEY,
base_branch VARCHAR,
base_commit VARCHAR,
interventions VARCHAR -- JSON array of intervention_ids
)

On non-scenario branches the bake is a no-op — the table is not created, so Compare can feature-detect via information_schema.

2. Compare server picks it up. When the Compare page loads each KLS to gather stats, it also queries scenario_metadata (best- effort, swallows the missing-table error). The new fields scenarioId, scenarioBase, scenarioInterventions land on the KlsVersion interface.

3. Compare UI surfaces scenarios distinctly.

  • The two <select> dropdowns split into <optgroup> blocks: “Production” (working + named snapshots) vs “Scenarios” (KLSes with baked metadata).
  • The side-by-side cards render a scenario panel below the existing build info when scenarioId is populated, listing the intervention IDs in an amber-tinted box.
  • A “Compare to production” button on the scenario card pre-fills the other side with the working KLS and navigates — one click from “I’m looking at this scenario” to “delta vs current production.”

Why the commit message as source of truth. The interventions applied to a scenario are determined at scenario-create time. The commit message that create_scenario wrote is git’s canonical record of that act. Reading it back at bake time keeps the metadata flowing without a sidecar file. If the commit gets amended into an unstructured shape, the bake gracefully no-ops (better no metadata than wrong metadata).

“What if?” button on Verdict detail → Scenario Builder → background build → notification → Simulation Results. Full loop in the browser. Not in scope for the 2026-05-22 weekend; the substrate is ready when it is.

The Simulation runs CLI-first today: jin scenario create branches the tenant AFS, applies one or more Interventions, and jin scenario build rebuilds the tenant against the modified framework. The resulting KLS is a true counter-factual — same engine, different input — and JinDesk can be pointed at it side by side with the baseline. The browser-side authoring surface for Suggestions and Interventions is the next layer; the substrate (AFS branching + scenario-aware make) is live.

  • CLI: jin scenario create <id> int_X [int_Y …] (branches AFS + applies Interventions) · jin scenario build <id> (rebuilds KLS on the scenario branch) · jin scenario list
  • Reads from: the tenant’s AFS (baseline) + intervention YAMLs · the baseline KLS for comparison
  • Writes to: scenario branch of tenant AFS · scenario KLS at kls/<scenario_id>_kls.duckdb

Status: shipped — CLI substrate live. The browser-side Suggestion / Intervention authoring surface is forming; the Phase 5b incremental build path is the next implementation target.

  1. Scope of Interventions: should Interventions only touch YAML (signals, theses, config), or also CSVs (seed data, reference tables)? Seed edits are powerful but harder to diff.
  2. Compound Scenarios: can a Scenario combine interventions from multiple Suggestions? (Yes, but the UX needs to handle conflicts.)
  3. Scenario persistence: scenarios are AFS branches — do they accumulate forever, or auto-prune after N days?
  4. Naming: “Simulation” implies continuous modeling. Is “Projection” better? Or “What-If Analysis”?
  5. Cost: a scenario build is a full jin make. For a 60s inspire build that’s fine. For a 10-minute RMC build, do we need a “fast simulation” mode that only rebuilds affected layers?
  6. Multi-tenant: can a scenario span multiple tenants? (Probably not — tenants are independent AFS instances.)
  7. Collaboration: can two users work on the same scenario? (AFS branches are git branches — standard git collaboration.)

Numerical neighbors:Sense 18: The Ledger — Computational Provenance as Narrative · Sense 19.1: The Simulation Prerequisites

jazzisnow jinflow is a jazzisnow product
v0.64.7 · built 2026-09-20 19:48 UTC