From d55bfe0fef33c4a0bab6874174a963704a300ae3 Mon Sep 17 00:00:00 2001 From: SebaSOFT Date: Mon, 22 Jun 2026 22:16:07 +0000 Subject: [PATCH 1/3] Add benchmark result data contract --- benchmarks/README.md | 9 + benchmarks/sample-results.placeholder.json | 115 ++++++++ docs/.vitepress/config.ts | 11 + docs/benchmarks/assets/README.md | 58 ++++ docs/benchmarks/index.md | 26 ++ docs/benchmarks/methodology.md | 93 ++++++ docs/benchmarks/prompt-kit.md | 315 +++++++++++++++++++++ docs/benchmarks/results.schema.json | 197 +++++++++++++ docs/benchmarks/visual-proof-system.md | 232 +++++++++++++++ package.json | 4 + tests/contracts/benchmark-contract.test.ts | 109 +++++++ yarn.lock | 97 +++++++ 12 files changed, 1266 insertions(+) create mode 100644 benchmarks/README.md create mode 100644 benchmarks/sample-results.placeholder.json create mode 100644 docs/benchmarks/assets/README.md create mode 100644 docs/benchmarks/index.md create mode 100644 docs/benchmarks/methodology.md create mode 100644 docs/benchmarks/prompt-kit.md create mode 100644 docs/benchmarks/results.schema.json create mode 100644 docs/benchmarks/visual-proof-system.md create mode 100644 tests/contracts/benchmark-contract.test.ts diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000..e01d83a --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,9 @@ +# Benchmark fixtures + +This directory contains benchmark data artifacts for NJS-GROWTH-07. + +- `sample-results.placeholder.json` is deterministic placeholder data for chart and playground wiring. +- It is not benchmark output and must not be used for public performance claims. +- Real benchmark output must match `docs/benchmarks/results.schema.json` and set `result_kind` to `actual_benchmark`. + +See `docs/benchmarks/methodology.md` for the competitor, scenario, input-size, and metric contract. diff --git a/benchmarks/sample-results.placeholder.json b/benchmarks/sample-results.placeholder.json new file mode 100644 index 0000000..c45b8f7 --- /dev/null +++ b/benchmarks/sample-results.placeholder.json @@ -0,0 +1,115 @@ +{ + "schema_version": "1.0.0", + "result_kind": "placeholder_sample", + "is_placeholder": true, + "claims_allowed": false, + "generated_at": "2026-01-01T00:00:00.000Z", + "disclaimer": "This file contains deterministic placeholder sample data for visual-agent wiring only. These are not benchmark results and must not be used as performance claims.", + "methodology": "docs/benchmarks/methodology.md", + "competitors": [ + "@sebasoft/neuron-js", + "json-rules-engine", + "json-logic-js", + "hand-coded-typescript", + "rule-engine-js" + ], + "scenarios": ["pricing-discount", "eligibility-approval", "workflow-routing"], + "input_sizes": ["smoke", "small", "medium", "large"], + "results": [ + { + "engine": "@sebasoft/neuron-js", + "scenario": "pricing-discount", + "input_size": "smoke", + "warmup_iterations": 10, + "measured_iterations": 100, + "throughput_decisions_per_second": 1000, + "p50_ms": 1, + "p95_ms": 2, + "cold_start_ms": 25, + "bundle_size_minified_bytes": 5000, + "validation_overhead_ms": 0.5, + "explanation_overhead_ms": 0.75, + "node_version": "v0.0.0-placeholder", + "package_version": "0.0.0-placeholder", + "commit_sha": "0000000000000000000000000000000000000000", + "result_kind": "placeholder_sample", + "notes": "synthetic placeholder row for chart wiring only; not benchmark results and not a performance claim." + }, + { + "engine": "json-rules-engine", + "scenario": "eligibility-approval", + "input_size": "smoke", + "warmup_iterations": 10, + "measured_iterations": 100, + "throughput_decisions_per_second": 1001, + "p50_ms": 1.1, + "p95_ms": 2.1, + "cold_start_ms": 26, + "bundle_size_minified_bytes": 5001, + "validation_overhead_ms": 0.6, + "explanation_overhead_ms": 0.85, + "node_version": "v0.0.0-placeholder", + "package_version": "0.0.0-placeholder", + "commit_sha": "0000000000000000000000000000000000000000", + "result_kind": "placeholder_sample", + "notes": "synthetic placeholder row for chart wiring only; not benchmark results and not a performance claim." + }, + { + "engine": "json-logic-js", + "scenario": "workflow-routing", + "input_size": "smoke", + "warmup_iterations": 10, + "measured_iterations": 100, + "throughput_decisions_per_second": 1002, + "p50_ms": 1.2, + "p95_ms": 2.2, + "cold_start_ms": 27, + "bundle_size_minified_bytes": 5002, + "validation_overhead_ms": 0.7, + "explanation_overhead_ms": 0.95, + "node_version": "v0.0.0-placeholder", + "package_version": "0.0.0-placeholder", + "commit_sha": "0000000000000000000000000000000000000000", + "result_kind": "placeholder_sample", + "notes": "synthetic placeholder row for chart wiring only; not benchmark results and not a performance claim." + }, + { + "engine": "hand-coded-typescript", + "scenario": "pricing-discount", + "input_size": "smoke", + "warmup_iterations": 10, + "measured_iterations": 100, + "throughput_decisions_per_second": 1003, + "p50_ms": 1.3, + "p95_ms": 2.3, + "cold_start_ms": 28, + "bundle_size_minified_bytes": 5003, + "validation_overhead_ms": 0.8, + "explanation_overhead_ms": 1.05, + "node_version": "v0.0.0-placeholder", + "package_version": "0.0.0-placeholder", + "commit_sha": "0000000000000000000000000000000000000000", + "result_kind": "placeholder_sample", + "notes": "synthetic placeholder row for chart wiring only; not benchmark results and not a performance claim." + }, + { + "engine": "rule-engine-js", + "scenario": "eligibility-approval", + "input_size": "smoke", + "warmup_iterations": 10, + "measured_iterations": 100, + "throughput_decisions_per_second": 1004, + "p50_ms": 1.4, + "p95_ms": 2.4, + "cold_start_ms": 29, + "bundle_size_minified_bytes": 5004, + "validation_overhead_ms": 0.9, + "explanation_overhead_ms": 1.15, + "node_version": "v0.0.0-placeholder", + "package_version": "0.0.0-placeholder", + "commit_sha": "0000000000000000000000000000000000000000", + "result_kind": "placeholder_sample", + "notes": "synthetic placeholder row for chart wiring only; not benchmark results and not a performance claim." + } + ] +} diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index abc523c..5d43ce1 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -12,6 +12,7 @@ export default defineConfig({ { text: 'Concepts', link: '/overview' }, { text: 'Examples', link: '/use-cases/runnable-examples' }, { text: 'Schemas', link: '/schemas-validation-explainability' }, + { text: 'Proof Assets', link: '/benchmarks/methodology' }, { text: 'Comparisons', link: '/comparisons/' }, { text: 'Integrations', link: '/integrations/' }, { text: 'AI Docs', link: '/ai-coding-assistants' }, @@ -42,6 +43,16 @@ export default defineConfig({ { text: 'Dynamic Routing', link: '/use-cases/dynamic-routing' } ] }, + { + text: 'Proof Assets', + items: [ + { text: 'Benchmarks & Visual Proof', link: '/benchmarks/' }, + { text: 'Benchmarks', link: '/benchmarks/methodology' }, + { text: 'Visual Proof System', link: '/benchmarks/visual-proof-system' }, + { text: 'Prompt Kit', link: '/benchmarks/prompt-kit' }, + { text: 'Asset Folder', link: '/benchmarks/assets/' } + ] + }, { text: 'Comparisons', items: [ diff --git a/docs/benchmarks/assets/README.md b/docs/benchmarks/assets/README.md new file mode 100644 index 0000000..acbe572 --- /dev/null +++ b/docs/benchmarks/assets/README.md @@ -0,0 +1,58 @@ +# NJS-GROWTH-07 benchmark asset folder + +Recommended folder for visual proof assets: + +```text +docs/benchmarks/assets/ + README.md + source-data/ + benchmark-results.example.json + benchmark-results.schema.json + prompts/ + benchmark-infographic.md + explainability-trace-diagram.md + playground-readme-gif-storyboard.md + ai-rule-safety-carousel.md + readme-proof-strip.md + storyboard/ + playground-readme-gif.md + generated/ + benchmark-chart-throughput.svg + benchmark-chart-cold-start.svg + benchmark-chart-bundle-size.svg + benchmark-chart-validation-overhead.svg + benchmark-chart-explanation-overhead.svg + explainability-trace-diagram.svg + readme-proof-strip.svg +``` + +## Folder rules + +- `source-data/` stores benchmark input data and schemas only. Generated assets must cite these files when they include measurements. +- `prompts/` stores frozen prompts copied or split from `docs/benchmarks/prompt-kit.md` for repeatable generation. +- `storyboard/` stores GIF/clip scripts, frame lists, and capture notes. +- `generated/` stores exported SVG/PNG/GIF/MP4 assets. + +## Data integrity rules + +- Do not place fabricated benchmark results in `source-data/`. +- Example files must be named `.example.*` and must use obviously non-claiming values or schema-only structures. +- Real benchmark files must include `node_version`, `package_version`, `commit_sha`, `warmup_iterations`, and `measured_iterations`. +- Any generated benchmark chart must name its source data file in adjacent metadata or in the SVG metadata block. + +## Accessibility rules + +Every final asset needs: + +- Alt text. +- Source data link when metrics appear. +- Color contrast check notes. +- Export dimensions. +- Creation date and generator/tool used. + +## README integration rule + +The README proof strip should not be merged into the README until either: + +1. it contains no benchmark numbers and is clearly a proof-structure asset; or +2. it uses real benchmark output from the harness and cites the exact source data. diff --git a/docs/benchmarks/index.md b/docs/benchmarks/index.md new file mode 100644 index 0000000..563ae04 --- /dev/null +++ b/docs/benchmarks/index.md @@ -0,0 +1,26 @@ +# Benchmarks and visual proof + +NJS-GROWTH-07 defines the public proof system for Neuron-JS benchmarks, playground captures, explanation diagrams, README media, and social proof assets. + +This section is a design and generation foundation. It does not publish benchmark claims. Benchmark numbers must come from measured harness output only. + +## Files + +- [Benchmark methodology and result contract](./methodology.md): competitor set, scenario matrix, input-size matrix, metric definitions, and placeholder-data policy. +- [Result JSON schema](./results.schema.json): machine-readable contract for benchmark output and downstream chart data. +- [Visual proof system](./visual-proof-system.md): palette, typography, composition, diagram style, chart rules, social-card constraints, and README proof strip guidance. +- [Visual proof prompt kit](./prompt-kit.md): reusable prompts for benchmark infographics, explainability trace diagrams, playground README GIF storyboards, AI-rule safety carousels, and README proof strips. +- [Asset folder recommendation](./assets/): recommended `docs/benchmarks/assets/` structure and data-integrity rules. + +## Proof promise + +Neuron-JS visual proof assets should make four claims visible: + +1. Rules are serializable JSON data. +2. Schema validation happens before runtime. +3. Execution is deterministic through a developer-owned registry and Synapse. +4. Explanation traces show why a rule matched or failed. + +## Data policy + +Do not fabricate benchmark results. When data is unavailable, use non-numeric structure, empty states, or labels such as `pending measured data`. diff --git a/docs/benchmarks/methodology.md b/docs/benchmarks/methodology.md new file mode 100644 index 0000000..b4142ef --- /dev/null +++ b/docs/benchmarks/methodology.md @@ -0,0 +1,93 @@ +# Neuron-JS benchmark methodology and result contract + +Source of record: `chaos-vault/50-research/neuron-js-growth-plan.md` lines 294-318, supported by `neuron-js-marketing-assets-benchmark.md` lines 87-100 and `neuron-js-social-demand-gap.md` lines 160-169. Hindsight recall was queried for this task and returned no relevant stored memories; the vault notes above are the governing source. + +This page defines the NJS-GROWTH-07 benchmark harness contract. It is intentionally conservative: no benchmark claim is valid until the executable harness emits `result_kind: "actual_benchmark"` with `is_placeholder: false` and `claims_allowed: true`. + +## Competitor set + +The harness/result contract covers exactly these engines for the first public proof bundle: + +| Engine | Adapter key | Role | +| --- | --- | --- | +| Neuron-JS | `@sebasoft/neuron-js` | First-party rules engine under test. | +| json-rules-engine | `json-rules-engine` | Closest default Node.js JSON rules-engine competitor. | +| JsonLogic | `json-logic-js` | Portable JSON predicate format competitor. | +| Hand-coded TypeScript | `hand-coded-typescript` | Baseline for direct conditional logic without engine overhead. | +| rule-engine-js | `rule-engine-js` | Smaller modern competitor selected because it installs/builds in this repository. | + +`rulepilot` remains an alternate candidate only if `rule-engine-js` becomes infeasible later. Do not mix both in the same first chart set without updating `docs/benchmarks/results.schema.json`. + +## Scenario matrix + +| Scenario | Inputs represented | Why it exists | +| --- | --- | --- | +| `pricing-discount` | tier, region, coupon, cart total, account age | Shows business-rule pricing decisions and validation/explanation overhead. | +| `eligibility-approval` | age, country, verification status, risk score, account flags | Shows policy/approval style decisions with clear pass/fail outcomes. | +| `workflow-routing` | channel, urgency, customer segment, confidence score, escalation flags | Shows deterministic workflow routing and trace usefulness. | + +## Input-size matrix + +| Profile | Decisions | Usage | +| --- | ---: | --- | +| `smoke` | 100 | Correctness and trace sanity. | +| `small` | 1,000 | Local development feedback. | +| `medium` | 10,000 | Chartable throughput. | +| `large` | 100,000 | Optional; run only if runtime remains practical in CI/local machines. | + +## Stable result fields + +Every result row must contain these fields. Units and source definitions are duplicated in `docs/benchmarks/results.schema.json` for machine consumers. + +| Field | Unit | Source | +| --- | --- | --- | +| `engine` | identifier | Harness adapter name for the implementation under test; fixed enum for cross-run joins. | +| `scenario` | identifier | Scenario slug produced by the benchmark scenario matrix. | +| `input_size` | profile | Named workload profile, not raw row count, so visual assets can group runs consistently. | +| `warmup_iterations` | decisions | Number of unmeasured warmup decisions completed before timing. | +| `measured_iterations` | decisions | Number of measured decisions included in timing statistics. | +| `throughput_decisions_per_second` | decisions/second | Measured decisions divided by elapsed measured wall-clock seconds. | +| `p50_ms` | milliseconds | Median per-decision latency from measured iterations. | +| `p95_ms` | milliseconds | 95th percentile per-decision latency from measured iterations. | +| `cold_start_ms` | milliseconds | Wall-clock time to load/import the engine adapter and execute the first decision in a fresh process or isolated worker. | +| `bundle_size_minified_bytes` | bytes | Minified adapter+engine bundle byte count from the configured bundler output. | +| `validation_overhead_ms` | milliseconds | Additional median latency for validation-enabled execution versus validation-disabled execution on the same scenario/input profile. | +| `explanation_overhead_ms` | milliseconds | Additional median latency for trace/explanation-enabled execution versus trace-disabled execution on the same scenario/input profile. | +| `node_version` | semver/runtime | Node.js version reported by `process.version` for the benchmark run. | +| `package_version` | semver or source | Package version or source label for the engine adapter under test. | +| `commit_sha` | git sha | Repository commit SHA for the Neuron-JS benchmark harness and local implementation. | + +## Placeholder data policy + +`benchmarks/sample-results.placeholder.json` is synthetic wiring data only. It exists so chart, carousel, README-strip, and playground work can consume stable fields before real measurements exist. + +Visual/publication agents must reject files where any of these are true: + +- `result_kind` is `placeholder_sample`. +- `is_placeholder` is `true`. +- `claims_allowed` is `false`. +- row `notes` contains `synthetic placeholder`. + +Synthetic sample values must never be used in README copy, social posts, npm copy, or public performance claims. + +## Initial harness contract + +A future executable harness should: + +1. Build adapters for `@sebasoft/neuron-js`, `json-rules-engine`, `json-logic-js`, `hand-coded-typescript`, and `rule-engine-js`. +2. Run each adapter against `pricing-discount`, `eligibility-approval`, and `workflow-routing` fixtures. +3. Execute `smoke`, `small`, and `medium` profiles by default; gate `large` behind an explicit flag. +4. Measure cold start separately from warm throughput. +5. Measure validation and explanation overhead as delta timings against the same scenario/input profile. +6. Emit JSON matching `docs/benchmarks/results.schema.json`. +7. Set `result_kind: "actual_benchmark"`, `is_placeholder: false`, and `claims_allowed: true` only for real measured output. + +## Visual asset consumers + +The first visual asset bundle can safely bind to these paths: + +- Schema: `docs/benchmarks/results.schema.json` +- Placeholder sample: `benchmarks/sample-results.placeholder.json` +- Methodology: `docs/benchmarks/methodology.md` + +Use the placeholder file for layout only. Replace it with real harness output before making any chart label, README proof strip, or social asset that implies measured performance. diff --git a/docs/benchmarks/prompt-kit.md b/docs/benchmarks/prompt-kit.md new file mode 100644 index 0000000..ecd61a6 --- /dev/null +++ b/docs/benchmarks/prompt-kit.md @@ -0,0 +1,315 @@ +# NJS-GROWTH-07 visual proof prompt kit + +This prompt kit is reusable input for downstream visual agents. It is intentionally data-safe: every benchmark prompt requires real measured data from a benchmark source file and forbids imagined values. + +Use alongside: + +- `docs/benchmarks/visual-proof-system.md` +- `docs/benchmarks/assets/README.md` + +Global source position: + +- Product wedge: TypeScript-first, explainable, schema-validatable JSON business rules for AI-assisted software and workflow automation. +- Proof objective: make Neuron-JS credible, inspectable, and useful beyond README claims. +- Data integrity rule: inject real benchmark measurements only. If measurements are missing, render schemas, empty states, or placeholder labels with no numeric claims. + +## Global prompt variables + +Fill these before generation: + +```yaml +project_name: "@sebasoft/neuron-js" +positioning: "AI-friendly TypeScript rules engine for serializable JSON business rules and deterministic workflow decisions" +scenario: "pricing-discount | eligibility-approval | workflow-routing" +input_size: "smoke | small | medium | large" +benchmark_source_path: "path/to/results.json-or.csv" +node_version: "actual Node.js version" +commit_sha: "actual benchmark commit SHA" +benchmark_date: "YYYY-MM-DD" +engines: + - "@sebasoft/neuron-js" + - "json-rules-engine" + - "json-logic-js / JsonLogic" + - "hand-coded TypeScript conditions" + - "rule-engine-js or rulepilot" +metrics: + - "throughput_decisions_per_second" + - "p50_ms" + - "p95_ms" + - "cold_start_ms" + - "bundle_size_minified_bytes" + - "validation_overhead_ms" + - "explanation_overhead_ms" +``` + +If any required variable is unknown, the generator must stop and request the missing source, or render a non-numeric placeholder clearly marked `sample structure only`. + +## 1. Benchmark infographic pack + +### Objective + +Create a benchmark infographic pack that compares Neuron-JS to `json-rules-engine`, JsonLogic, hand-coded TypeScript conditions, and one smaller modern competitor using honest measured data. + +The asset should make methodology visible before claims. + +### Prompt + +```text +Create a dark technical benchmark infographic pack for @sebasoft/neuron-js. + +Objective: +Show credible, inspectable benchmark evidence for a TypeScript-first, explainable, schema-validatable JSON business rules engine. Compare @sebasoft/neuron-js against json-rules-engine, json-logic-js / JsonLogic, hand-coded TypeScript conditions, and [rule-engine-js or rulepilot]. Do not imply a winner unless the provided benchmark data proves it. + +Data source: +Use only benchmark data from: [benchmark_source_path]. +Required fields: engine, scenario, input_size, warmup_iterations, measured_iterations, throughput_decisions_per_second, p50_ms, p95_ms, cold_start_ms, bundle_size_minified_bytes, validation_overhead_ms, explanation_overhead_ms, node_version, package_version, commit_sha. +If any numeric value is missing, render an empty state or label it as "pending measured data". Never invent or approximate numbers. + +Layout: +Dashboard + comparison matrix. +Canvas: 16:9 for docs hero, plus export-safe variants at 1:1 and 4:5. +Top band: title, scenario, input size, benchmark date, Node version, commit SHA. +Main grid: +1. Throughput chart: decisions per second by engine. +2. Latency chart: p50_ms and p95_ms by engine. +3. Cold start chart: cold_start_ms by engine. +4. Bundle size chart: minified bytes by engine. +5. Validation overhead chart: validation_overhead_ms by engine. +6. Explanation overhead chart: explanation_overhead_ms by engine. +Bottom band: methodology strip with warmup iterations, measured iterations, package versions, and "measured data only" note. + +Text labels: +- Main title: "Measured proof for JSON business rules" +- Subtitle: "Validate -> Execute -> Explain -> Compare" +- Method label: "No synthetic benchmark values. Source: [benchmark_source_path]" +- Engine labels exactly as provided in the data source. +- Metric labels exactly matching the schema field names or their readable equivalents. + +Visual hierarchy: +Use @sebasoft/neuron-js cyan as the identity color but keep equal chart scale and honest comparison. Use dark panels, faint grid, monospace metric labels, and small methodology footnotes. Make the data source and commit SHA visible, not hidden. + +Style: +Dark technical schematic, crisp dashboard, no 3D charts, no mascot, no generic SaaS gradients. Use semantic colors: cyan for Neuron-JS/inspectability, emerald for validation/pass, violet for explainability, amber for method/caution, rose for errors or warnings, slate for neutral competitors. + +Negative constraints: +Do not fabricate benchmark results. Do not use fake numbers, lorem ipsum, unlabeled axes, cropped axes, trophy icons, "fastest" claims, or decorative data marks. Do not show Neuron-JS as winning unless real source data establishes that outcome. Do not include generic AI robot imagery. + +Reproducibility notes: +Output should include alt text, exact data source path, Node version, package versions, commit SHA, benchmark date, and export dimensions. Keep generated source editable as SVG/HTML or layered design file where possible. +``` + +### Verification checklist + +- Every visible number exists in the benchmark source file. +- Axis labels and metric names are correct. +- Methodology strip includes Node version, commit SHA, warmup iterations, and measured iterations. +- Alt text names the scenario, metric group, and no-fabrication policy. + +## 2. Explainability trace diagram + +### Objective + +Create a diagram that explains how JSON rules move through validation, developer registry constraints, deterministic execution, result output, and explanation trace. + +### Prompt + +```text +Create a dark SVG-style explainability trace diagram for @sebasoft/neuron-js. + +Objective: +Make Neuron-JS inspectability visible. Show how serializable JSON business rules become deterministic decisions with schema validation and an audit-friendly explanation trace. + +Layout: +Linear progression / structural breakdown, 16:9. +Flow left to right: +1. Rule JSON +2. Schema validation +3. Developer-owned registry +4. Synapse deterministic execution +5. Result object +6. Explanation trace +7. Audit / review +Add a secondary error branch from Schema validation to Validation errors -> Repair loop. Add a secondary safety note from Developer-owned registry to "Only approved actions, conditions, parameters, and rules can execute." + +Text labels: +- Title: "From JSON rule to explainable decision" +- Rule JSON panel: "Serializable script" +- Validation panel: "Schema-first validation" +- Registry panel: "Developer-approved vocabulary" +- Execution panel: "Synapse runs deterministically" +- Result panel: "Decision result" +- Trace panel: "Why it matched or failed" +- Error branch: "Validation errors show exact repair paths" + +Visual hierarchy: +Main path uses cyan active arrows. Validation pass uses emerald check markers. Explainability trace uses violet audit-chain accents. Error/repair branch uses rose dashed lines. Keep all boxes aligned to a faint grid with adequate spacing. + +Style: +Dark technical architecture diagram, rounded rectangles, 1.5px strokes, JetBrains Mono labels, subtle grid background, no JavaScript animation required. Use concise JSON snippets inside the Rule JSON and Trace panels, but keep them readable. + +Negative constraints: +Do not show arbitrary code execution. Do not show business users directly running unsafe generated rules. Do not use magic wand, robot, black-box AI, or vague cloud icons. Do not include benchmark numbers. + +Reproducibility notes: +Deliver as standalone SVG or self-contained HTML with inline SVG. Include alt text and a source note referencing docs/schemas-validation-explainability.md. Verify it renders in a browser. +``` + +### Verification checklist + +- The error branch teaches repair, not failure panic. +- The registry is visible as the control boundary. +- Diagram fits README/docs width without tiny labels. + +## 3. Playground README GIF storyboard + +### Objective + +Storyboard a short GIF that proves the playground is useful: edit rule JSON and input JSON, validate, run, inspect result, inspect trace, and share state. + +### Prompt + +```text +Create a storyboard for a short README GIF demonstrating the Neuron-JS playground. + +Objective: +Show public proof that Neuron-JS is inspectable and useful beyond README claims. The GIF should demonstrate a deterministic pricing or eligibility decision using rule JSON, input JSON, validation, result output, trace inspection, validation errors, and shareable state. + +Layout: +Storyboard with 6 frames, 16:9. +Frame 1: Playground opens with scenario selector set to [pricing-discount or eligibility-approval]. +Frame 2: Rule JSON and input JSON panels are visible side-by-side. +Frame 3: User clicks Validate; schema pass state appears with emerald check. +Frame 4: User clicks Run; result panel shows deterministic decision output. +Frame 5: User opens Trace; trace rows explain why a rule matched or failed. +Frame 6: User changes one invalid field; validation error highlights JSON path, then Share URL state appears. + +Text labels: +- Frame 1: "Choose a business decision" +- Frame 2: "Inspect rule JSON + input JSON" +- Frame 3: "Validate before runtime" +- Frame 4: "Run deterministic decision" +- Frame 5: "Explain why it matched" +- Frame 6: "Repair errors and share state" + +Visual hierarchy: +The active interaction should be highlighted with a cyan focus ring. Validation success uses emerald. Validation errors use rose with exact path labels. Trace panel uses violet. Keep UI controls large enough for README viewing. + +Style: +Crisp product UI mock, dark technical theme, accessible contrast, minimal motion. Use realistic UI structure: tabs, split panes, JSON editor, result card, trace list, validation error list, share button. Motion should be a calm cursor/click sequence, not flashy animation. + +Negative constraints: +Do not include fake benchmark numbers. Do not show arbitrary code execution. Do not imply business users can safely publish generated rules without validation, tests, and approval. Avoid generic dashboard art or decorative robot imagery. + +Reproducibility notes: +When the real playground exists, capture from the actual UI and keep the storyboard labels as title overlays only if needed. Export target: GIF under 5 MB for README, plus MP4/WebM fallback if the docs site supports it. Include alt text and exact capture command/tool in the asset metadata. +``` + +### Verification checklist + +- Every frame has a single visible learning point. +- Error state and empty/pending state are included. +- Shareable state appears only if implemented in the playground. + +## 4. AI-generated-rule safety carousel/comic + +### Objective + +Create an educational carousel showing that Neuron-JS is not “AI magic”; it is a deterministic guardrail layer for generated rules. + +### Prompt + +```text +Create a 5-slide technical comic carousel for @sebasoft/neuron-js about safe AI-generated JSON rules. + +Objective: +Explain the safety story: LLMs can draft rules, but Neuron-JS makes execution safe only through schema validation, developer-owned registry boundaries, tests, approvals, rollback, deterministic execution, and explanation traces. + +Layout: +Bridge/funnel narrative, 4:5 vertical carousel. +Slide 1: Problem — "LLMs can draft rules. They cannot be trusted blindly." +Slide 2: Gate 1 — "Schema validation catches malformed JSON scripts." +Slide 3: Gate 2 — "Developer registry limits the executable vocabulary." +Slide 4: Gate 3 — "Tests, approvals, and rollback before production." +Slide 5: Outcome — "Deterministic execution with an explanation trace." + +Text labels: +- Main headline: "AI drafts. Neuron-JS verifies." +- Supporting labels: "Rules as data", "Schema-first", "Approved vocabulary", "Traceable decisions", "No arbitrary code" +- Footer: "@sebasoft/neuron-js — TypeScript-first JSON business rules" + +Visual hierarchy: +Use a left-to-right or top-to-bottom safety-gate sequence. The LLM draft starts as amber/pending, invalid paths are rose and blocked, valid path turns emerald after validation, deterministic execution is cyan, explanation trace is violet. + +Style: +Technical comic, not childish. Clean panels, limited characters if any, focus on artifacts: JSON card, schema gate, registry box, test checklist, approval stamp, trace rows. Use dark theme and precise labels. + +Negative constraints: +No robot savior imagery. No claim that AI-generated rules are safe automatically. No fake metrics. No vague "autonomous business logic" promise. Do not depict non-technical users publishing rules without review. + +Reproducibility notes: +Each slide must include editable text layers or markdown captions. Include alt text per slide. Keep same palette, typography, and engine proof language as visual-proof-system.md. +``` + +### Verification checklist + +- The carousel explicitly blocks unsafe generation. +- It includes review/approval/rollback, not only validation. +- It reinforces deterministic execution and explanation trace. + +## 5. README proof strip + +### Objective + +Create a compact README strip that makes the trust story visible in one glance. + +### Prompt + +```text +Create a compact README proof strip for @sebasoft/neuron-js. + +Objective: +Give README visitors immediate visual proof that Neuron-JS validates JSON rules, executes deterministic decisions, explains traces, and supports honest benchmarks/playground proof. + +Layout: +Wide strip, 5:1 or 4:1 aspect ratio, export as SVG and PNG. +Four panels across the strip: +1. Validate +2. Execute +3. Explain +4. Compare +Each panel has one artifact: validation error/pass row, execution result card, trace row, benchmark chart placeholder or real chart if measured data exists. + +Text labels: +- Main title: "JSON rules you can validate, run, and explain" +- Panel 1: "Validate: schema-first checks" +- Panel 2: "Execute: deterministic Synapse run" +- Panel 3: "Explain: trace why it matched" +- Panel 4: "Compare: measured benchmarks only" +- Footnote if benchmark data is pending: "Benchmark slot shown as structure only until measured data is available." + +Visual hierarchy: +The strip must be readable at README width. Use large panel titles, small but legible monospace snippets, and clear iconography based on artifacts, not generic symbols. Use cyan as the connecting thread, emerald for valid states, rose for error examples, violet for trace, amber for benchmark methodology. + +Style: +Dark product evidence strip, technical but clean. No decorative background beyond a faint grid. Sharp, inspectable mini-panels. + +Negative constraints: +Do not include fake benchmark values. Do not include tiny unreadable JSON blocks. Do not use badges that imply verified metrics without source data. Avoid generic SaaS hero art. + +Reproducibility notes: +Store source file under docs/benchmarks/assets/generated/ or docs/public/img/ when finalized. Include alt text in README integration. If using real chart data, include source path, Node version, package versions, and commit SHA in hidden SVG metadata or adjacent markdown. +``` + +### Verification checklist + +- Works at README width. +- Uses real data or clearly non-numeric placeholders. +- Has an alt-text-ready description. + +## Downstream asset tasks recommended + +1. Generate `explainability-trace-diagram` as standalone SVG/HTML once docs wording is final. +2. Generate `README-proof-strip` after selecting whether it will use non-numeric proof structure or real benchmark data. +3. Generate `benchmark-chart-throughput`, `benchmark-chart-cold-start`, `benchmark-chart-bundle-size`, `benchmark-chart-validation-overhead`, and `benchmark-chart-explanation-overhead` only after benchmark harness outputs real data. +4. Capture `playground-demo-gif-storyboard` from the actual playground once validation, trace, errors, and shareable state are implemented. +5. Generate `ai-rule-safety-carousel` as social proof after review of copy/legal risk around AI-generated rules. diff --git a/docs/benchmarks/results.schema.json b/docs/benchmarks/results.schema.json new file mode 100644 index 0000000..51c1a08 --- /dev/null +++ b/docs/benchmarks/results.schema.json @@ -0,0 +1,197 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://sebasoft.github.io/neuron-js/benchmarks/results.schema.json", + "title": "Neuron-JS benchmark result contract", + "description": "Stable machine-readable result format for NJS-GROWTH-07 benchmark and visual-proof assets. Placeholder fixtures are explicitly non-claim data.", + "type": "object", + "required": [ + "schema_version", + "result_kind", + "is_placeholder", + "claims_allowed", + "generated_at", + "methodology", + "competitors", + "scenarios", + "input_sizes", + "results" + ], + "properties": { + "schema_version": { "type": "string" }, + "result_kind": { "type": "string", "enum": ["actual_benchmark", "placeholder_sample"] }, + "is_placeholder": { "type": "boolean" }, + "claims_allowed": { "type": "boolean" }, + "generated_at": { "type": "string", "format": "date-time" }, + "disclaimer": { "type": "string" }, + "methodology": { "type": "string" }, + "competitors": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "@sebasoft/neuron-js", + "json-rules-engine", + "json-logic-js", + "hand-coded-typescript", + "rule-engine-js" + ] + } + }, + "scenarios": { + "type": "array", + "items": { + "type": "string", + "enum": ["pricing-discount", "eligibility-approval", "workflow-routing"] + } + }, + "input_sizes": { + "type": "array", + "items": { + "type": "string", + "enum": ["smoke", "small", "medium", "large"] + } + }, + "results": { + "type": "array", + "items": { + "type": "object", + "required": [ + "engine", + "scenario", + "input_size", + "warmup_iterations", + "measured_iterations", + "throughput_decisions_per_second", + "p50_ms", + "p95_ms", + "cold_start_ms", + "bundle_size_minified_bytes", + "validation_overhead_ms", + "explanation_overhead_ms", + "node_version", + "package_version", + "commit_sha" + ], + "properties": { + "engine": { + "type": "string", + "enum": ["@sebasoft/neuron-js", "json-rules-engine", "json-logic-js", "hand-coded-typescript", "rule-engine-js"], + "unit": "identifier", + "source": "Harness adapter name for the implementation under test; fixed enum for cross-run joins.", + "description": "Harness adapter name for the implementation under test; fixed enum for cross-run joins." + }, + "scenario": { + "type": "string", + "enum": ["pricing-discount", "eligibility-approval", "workflow-routing"], + "unit": "identifier", + "source": "Scenario slug produced by the benchmark scenario matrix.", + "description": "Scenario slug produced by the benchmark scenario matrix." + }, + "input_size": { + "type": "string", + "enum": ["smoke", "small", "medium", "large"], + "unit": "profile", + "source": "Named workload profile, not raw row count, so visual assets can group runs consistently.", + "description": "Named workload profile, not raw row count, so visual assets can group runs consistently." + }, + "warmup_iterations": { + "type": "integer", + "minimum": 0, + "unit": "decisions", + "source": "Number of unmeasured warmup decisions completed before timing.", + "description": "Number of unmeasured warmup decisions completed before timing." + }, + "measured_iterations": { + "type": "integer", + "minimum": 1, + "unit": "decisions", + "source": "Number of measured decisions included in timing statistics.", + "description": "Number of measured decisions included in timing statistics." + }, + "throughput_decisions_per_second": { + "type": "number", + "minimum": 0, + "unit": "decisions/second", + "source": "Measured decisions divided by elapsed measured wall-clock seconds.", + "description": "Measured decisions divided by elapsed measured wall-clock seconds." + }, + "p50_ms": { + "type": "number", + "minimum": 0, + "unit": "milliseconds", + "source": "Median per-decision latency from measured iterations.", + "description": "Median per-decision latency from measured iterations." + }, + "p95_ms": { + "type": "number", + "minimum": 0, + "unit": "milliseconds", + "source": "95th percentile per-decision latency from measured iterations.", + "description": "95th percentile per-decision latency from measured iterations." + }, + "cold_start_ms": { + "type": "number", + "minimum": 0, + "unit": "milliseconds", + "source": "Wall-clock time to load/import the engine adapter and execute the first decision in a fresh process or isolated worker.", + "description": "Wall-clock time to load/import the engine adapter and execute the first decision in a fresh process or isolated worker." + }, + "bundle_size_minified_bytes": { + "type": "integer", + "minimum": 0, + "unit": "bytes", + "source": "Minified adapter+engine bundle byte count from the configured bundler output.", + "description": "Minified adapter+engine bundle byte count from the configured bundler output." + }, + "validation_overhead_ms": { + "type": "number", + "minimum": 0, + "unit": "milliseconds", + "source": "Additional median latency for validation-enabled execution versus validation-disabled execution on the same scenario/input profile.", + "description": "Additional median latency for validation-enabled execution versus validation-disabled execution on the same scenario/input profile." + }, + "explanation_overhead_ms": { + "type": "number", + "minimum": 0, + "unit": "milliseconds", + "source": "Additional median latency for trace/explanation-enabled execution versus trace-disabled execution on the same scenario/input profile.", + "description": "Additional median latency for trace/explanation-enabled execution versus trace-disabled execution on the same scenario/input profile." + }, + "node_version": { + "type": "string", + "unit": "semver/runtime", + "source": "Node.js version reported by process.version for the benchmark run.", + "description": "Node.js version reported by process.version for the benchmark run." + }, + "package_version": { + "type": "string", + "unit": "semver or source", + "source": "Package version or source label for the engine adapter under test.", + "description": "Package version or source label for the engine adapter under test." + }, + "commit_sha": { + "type": "string", + "unit": "git sha", + "source": "Repository commit SHA for the Neuron-JS benchmark harness and local implementation.", + "description": "Repository commit SHA for the Neuron-JS benchmark harness and local implementation." + }, + "result_kind": { + "type": "string", + "enum": ["actual_benchmark", "placeholder_sample"], + "unit": "classification", + "source": "Set by harness output mode.", + "description": "Distinguishes measured results from non-claim sample fixtures." + }, + "notes": { + "type": "string", + "unit": "free text", + "source": "Human or harness annotation.", + "description": "Required caveats, methodology notes, or placeholder warnings." + } + }, + "additionalProperties": true + } + } + }, + "additionalProperties": false +} diff --git a/docs/benchmarks/visual-proof-system.md b/docs/benchmarks/visual-proof-system.md new file mode 100644 index 0000000..32f03d9 --- /dev/null +++ b/docs/benchmarks/visual-proof-system.md @@ -0,0 +1,232 @@ +# NJS-GROWTH-07 visual proof system + +Status: design foundation for downstream benchmark, playground, README, and social proof assets. + +Source of record: + +- `chaos-vault/50-research/neuron-js-growth-plan.md`, `NJS-GROWTH-07` lines 294-318: proof assets must cover benchmarks, playground, and visual explanation. +- `chaos-vault/50-research/neuron-js-marketing-assets-benchmark.md`, lines 87-100 and 160-174: publish honest benchmarks, shareable playground proof, trace panel, README GIF. +- `chaos-vault/50-research/neuron-js-social-demand-gap.md`, lines 184-210: trust wedge is TypeScript-first, explainable, schema-validatable JSON business rules for AI-assisted software and workflow automation. + +Do not use this system to invent performance numbers. Benchmark visuals must use measured data from the benchmark harness only. + +## Brand proof thesis + +Neuron-JS should look like deterministic infrastructure, not generic SaaS marketing. + +The visual system must communicate four claims: + +1. Credible: honest methodology, visible competitor set, clear metric definitions. +2. Inspectable: rule JSON, input JSON, result, validation errors, and explanation trace are shown as first-class panels. +3. Deterministic: decisions flow through explicit validation and execution gates, not probabilistic magic. +4. AI-safe: generated rules are constrained by schemas, registry vocabulary, previews, approvals, tests, and rollback. + +## Audience and surfaces + +Primary audience: + +- TypeScript developers choosing between rule engines, hand-coded conditions, or workflow platforms. +- Engineering leads evaluating whether dynamic JSON rules can be trusted. +- AI workflow builders who need deterministic guardrails after LLM extraction or classification. + +Primary surfaces: + +- `docs/benchmarks/` pages. +- `docs/playground/` or future playground package/site. +- README proof strip and short GIF. +- Social cards and carousels for X/LinkedIn/GitHub discussions. + +## Palette + +Use a dark technical base with precise semantic accent colors. Cyberpunk energy is allowed only as a restrained proof-of-system glow, not decoration. + +| Token | Hex | Role | Usage | +| --- | --- | --- | --- | +| `proof-bg` | `#020617` | slate black | page/card background, chart canvas | +| `proof-panel` | `#0f172a` | raised panel | JSON panes, chart cards, trace rows | +| `proof-panel-2` | `#111827` | secondary panel | nested code and metadata | +| `proof-grid` | `#1e293b` | grid lines | faint chart grids, diagram scaffolds | +| `proof-text` | `#e5e7eb` | primary text | labels, titles, high-contrast body text | +| `proof-muted` | `#94a3b8` | secondary text | captions, method notes, axis labels | +| `proof-cyan` | `#22d3ee` | Neuron-JS / inspectability | main highlight, active flow, trace focus | +| `proof-emerald` | `#34d399` | validation/pass | schema pass, deterministic execution success | +| `proof-violet` | `#a78bfa` | explainability | trace and audit chain | +| `proof-amber` | `#fbbf24` | benchmark method | methodology callouts, caution labels | +| `proof-rose` | `#fb7185` | errors/safety | validation errors, unsafe generation, blocked paths | + +Color rules: + +- Never encode benchmark rank by arbitrary rainbow colors. Use a stable engine mapping. +- Use color plus labels/patterns, never color alone. +- Keep chart backgrounds dark and data marks high contrast. +- For accessibility, maintain WCAG AA contrast for every text label. + +## Engine color mapping + +Use this order consistently across all benchmark assets: + +| Engine | Color | Stroke/pattern note | +| --- | --- | --- | +| `@sebasoft/neuron-js` | `proof-cyan` / `#22d3ee` | solid line, highlighted but not oversized | +| `json-rules-engine` | `proof-violet` / `#a78bfa` | solid line, equal weight | +| `json-logic-js` / JsonLogic | `proof-amber` / `#fbbf24` | dashed line or patterned bar | +| hand-coded TypeScript | `proof-emerald` / `#34d399` | solid line, marked as baseline not product competitor | +| `rule-engine-js` or `rulepilot` | `proof-muted` / `#94a3b8` | dotted or lower-emphasis stroke | + +Do not visually imply Neuron-JS wins unless the measured benchmark data proves it. + +## Typography + +Preferred stack: + +- UI and headings: `Inter`, `system-ui`, `-apple-system`, `BlinkMacSystemFont`, `Segoe UI`, sans-serif. +- Code and metric labels: `JetBrains Mono`, `SFMono-Regular`, `Menlo`, `Consolas`, monospace. + +Type scale: + +| Token | Size | Weight | Usage | +| --- | --- | --- | --- | +| `display` | 40-48px | 700 | hero/README strip headline | +| `title` | 28-32px | 700 | infographic title | +| `section` | 18-22px | 650 | panel headers | +| `body` | 14-16px | 400-500 | explanatory copy | +| `mono-label` | 12-13px | 500 | JSON keys, axis labels, trace node labels | +| `micro` | 10-11px | 500 | metadata, commit SHA, version, methodology footnotes | + +Rules: + +- Keep headlines concrete: `Validate -> Execute -> Explain`, not vague claims. +- Use code labels where the source artifact is code or JSON. +- Use short captions that explain what is inspectable. + +## Composition system + +Use a three-layer composition model: + +1. Evidence layer: charts, JSON panes, trace nodes, validation rows. +2. Interpretation layer: small annotations explaining what the viewer can trust. +3. Method layer: metric schema, versions, input sizes, commit SHA, and no-fabrication note. + +Preferred layouts by asset: + +| Asset | Layout | Style | +| --- | --- | --- | +| benchmark infographic pack | dashboard + comparison matrix | technical schematic, dark lab grid | +| explainability trace diagram | linear progression or structural breakdown | dark architecture diagram | +| playground README GIF storyboard | comic-strip sequence + UI wireframe | crisp product UI, low ornament | +| AI-generated-rule safety carousel | bridge or funnel | technical comic with safety gates | +| README proof strip | bento-grid / proof strip | compact dark product evidence card | + +## Diagram style + +Trace and architecture diagrams should use dark SVG-style panels: + +- Rounded rectangles with 6-8px radius. +- 1.5px strokes. +- Faint 40px grid background. +- Arrows behind boxes. +- Dashed rose lines for blocked unsafe paths. +- Emerald check markers for validation pass. +- Violet audit chain for explainability trace. +- Cyan active path for Neuron-JS execution. + +Canonical trace flow: + +```text +Rule JSON -> Schema validation -> Developer registry -> Synapse execution -> Result -> Explanation trace -> Audit/review +``` + +AI-safety flow: + +```text +LLM draft -> schema validation -> registry vocabulary check -> test cases -> human approval -> deterministic execution + \-> validation errors -> repair loop +``` + +## Chart rules + +Benchmark visuals must display method before claim. + +Required chart metadata: + +- scenario: `pricing-discount`, `eligibility-approval`, or `workflow-routing`. +- input size: smoke / small / medium / large. +- warmup iterations. +- measured iterations. +- Node version. +- package versions. +- commit SHA. +- benchmark date. + +Allowed metrics: + +- throughput decisions per second. +- p50 and p95 milliseconds. +- cold start milliseconds. +- bundle size minified bytes. +- validation overhead milliseconds. +- explanation overhead milliseconds. + +Forbidden chart behavior: + +- No invented numbers. +- No unlabeled axes. +- No “fastest” badge without measured proof. +- No 3D charts. +- No cropped axes that exaggerate differences. +- No benchmark screenshot without methodology metadata. + +## Social-card constraints + +Use these constraints for X/LinkedIn/GitHub visual posts: + +- Default social aspect: 16:9 for link cards, 1:1 for feed cards, 4:5 for LinkedIn carousel slides. +- Maximum headline length: 8 words. +- Maximum body text per slide: 35 words. +- Minimum font size: 28px for headline on 1200px-wide assets; 18px for labels. +- Always include the package name `@sebasoft/neuron-js`. +- Add a footnote if numbers are benchmark-specific: `Measured on , . See methodology.` +- For unreleased/prototype assets, include `sample structure only — replace with measured data`. + +## README proof strip recommendation + +Recommended asset folder: + +```text +docs/benchmarks/assets/ + README.md + source-data/ + generated/ + prompts/ + storyboard/ +``` + +README strip design: + +- Aspect ratio: wide 5:1 or 4:1, exportable as SVG/PNG and embeddable in README. +- Sections: `Validate`, `Execute`, `Explain`, `Compare`. +- Must show one actual tiny trace row or JSON snippet, not generic icons only. +- If benchmark numbers are not final, use placeholder labels such as `throughput`, `cold start`, `bundle size` without fake values. + +## Accessibility and QA gates + +Before an asset is approved: + +- Verify text contrast reaches WCAG AA minimum. +- Check legibility at 50% scale for README and social use. +- Ensure keyboard-visible UI states exist for any playground capture. +- Add alt text for every exported image. +- Keep all chart data traceable to a source CSV/JSON and commit SHA. +- Confirm every metric label matches the benchmark schema exactly. + +## Brand guardian checks + +Reject assets that: + +- Make Neuron-JS look like a no-code magic builder. +- Hide the developer-owned registry or schema validation story. +- Use fake benchmark numbers or decorative data. +- Use generic robot/AI imagery without validation and deterministic execution gates. +- Overpromise business-user rule authoring without review, tests, and rollback. + +Approve assets that make the trust story visible: rules are data, execution is deterministic, validation is schema-first, traces are inspectable, and AI generation is constrained. diff --git a/package.json b/package.json index 81ecdea..574f8a8 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,11 @@ "devDependencies": { "@biomejs/biome": "^2.4.13", "@changesets/cli": "^2.31.0", + "@types/json-logic-js": "^2", "@types/node": "^25.6.0", + "json-logic-js": "^2.0.5", + "json-rules-engine": "^7.3.1", + "rule-engine-js": "^1.0.7", "tshy": "^4.1.1", "typedoc": "^0.28.19", "typedoc-plugin-markdown": "^4.11.0", diff --git a/tests/contracts/benchmark-contract.test.ts b/tests/contracts/benchmark-contract.test.ts new file mode 100644 index 0000000..2d3442c --- /dev/null +++ b/tests/contracts/benchmark-contract.test.ts @@ -0,0 +1,109 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { describe, expect, it } from 'vitest'; + +const requiredFields = [ + 'engine', + 'scenario', + 'input_size', + 'warmup_iterations', + 'measured_iterations', + 'throughput_decisions_per_second', + 'p50_ms', + 'p95_ms', + 'cold_start_ms', + 'bundle_size_minified_bytes', + 'validation_overhead_ms', + 'explanation_overhead_ms', + 'node_version', + 'package_version', + 'commit_sha', +]; + +const requiredEngines = [ + '@sebasoft/neuron-js', + 'json-rules-engine', + 'json-logic-js', + 'hand-coded-typescript', + 'rule-engine-js', +]; + +const requiredScenarios = [ + 'pricing-discount', + 'eligibility-approval', + 'workflow-routing', +]; + +const requiredInputSizes = ['smoke', 'small', 'medium', 'large']; + +function readJson(path: string) { + return JSON.parse(readFileSync(path, 'utf8')) as Record; +} + +describe('benchmark result-data contract', () => { + it('publishes methodology, JSON schema, and placeholder sample data files', () => { + expect(existsSync('docs/benchmarks/methodology.md')).toBe(true); + expect(existsSync('docs/benchmarks/results.schema.json')).toBe(true); + expect(existsSync('benchmarks/sample-results.placeholder.json')).toBe(true); + }); + + it('defines every NJS-GROWTH-07 metric with a stable type, unit, and source note', () => { + const schema = readJson('docs/benchmarks/results.schema.json'); + const resultProperties = ((schema.properties as Record).results as Record).items as Record; + const properties = resultProperties.properties as Record>; + const required = resultProperties.required as string[]; + + for (const field of requiredFields) { + expect(required).toContain(field); + expect(properties[field]).toBeDefined(); + expect(properties[field].description).toEqual(expect.any(String)); + expect(properties[field].description as string).not.toHaveLength(0); + expect(properties[field].unit).toEqual(expect.any(String)); + expect(properties[field].source).toEqual(expect.any(String)); + } + }); + + it('links benchmark methodology from VitePress navigation and sidebar', () => { + const config = readFileSync('docs/.vitepress/config.ts', 'utf8'); + + expect(config).toContain("{ text: 'Benchmarks', link: '/benchmarks/methodology' }"); + }); + + it('documents the complete competitor, scenario, and input-size matrix', () => { + const methodology = readFileSync('docs/benchmarks/methodology.md', 'utf8'); + const schema = readFileSync('docs/benchmarks/results.schema.json', 'utf8'); + + for (const engine of requiredEngines) { + expect(methodology).toContain(engine); + expect(schema).toContain(engine); + } + + for (const scenario of requiredScenarios) { + expect(methodology).toContain(scenario); + expect(schema).toContain(scenario); + } + + for (const size of requiredInputSizes) { + expect(methodology).toContain(size); + expect(schema).toContain(size); + } + }); + + it('marks sample data as placeholder and prevents accidental benchmark claims', () => { + const sample = readJson('benchmarks/sample-results.placeholder.json'); + + expect(sample.result_kind).toBe('placeholder_sample'); + expect(sample.is_placeholder).toBe(true); + expect(sample.claims_allowed).toBe(false); + expect(sample.disclaimer).toEqual(expect.stringContaining('not benchmark results')); + + const rows = sample.results as Record[]; + expect(rows.length).toBeGreaterThan(0); + for (const row of rows) { + for (const field of requiredFields) { + expect(row).toHaveProperty(field); + } + expect(row.result_kind).toBe('placeholder_sample'); + expect(row.notes).toEqual(expect.stringContaining('synthetic placeholder')); + } + }); +}); diff --git a/yarn.lock b/yarn.lock index 0b1af6e..05f6966 100644 --- a/yarn.lock +++ b/yarn.lock @@ -860,6 +860,24 @@ __metadata: languageName: node linkType: hard +"@jsep-plugin/assignment@npm:^1.3.0": + version: 1.3.0 + resolution: "@jsep-plugin/assignment@npm:1.3.0" + peerDependencies: + jsep: ^0.4.0||^1.0.0 + checksum: 10c0/d749554dc691798116eb068eebe2d9bcb0b0d89ef6c7cc7c2a9f37d03da15fdbf8053407e97008090cd1bd6f256ea6c26abbada7399cf79f0b6b502e164b084b + languageName: node + linkType: hard + +"@jsep-plugin/regex@npm:^1.0.4": + version: 1.0.4 + resolution: "@jsep-plugin/regex@npm:1.0.4" + peerDependencies: + jsep: ^0.4.0||^1.0.0 + checksum: 10c0/bec7eb7ea6ab453a2672edc808644c5be3dc06b2a9d77182e18cd595b37deba6dcdb3760849d8684afc5779a86b7d2604dd525cb612a548f9ed9f31a8032ec24 + languageName: node + linkType: hard + "@manypkg/find-root@npm:^1.1.0": version: 1.1.0 resolution: "@manypkg/find-root@npm:1.1.0" @@ -1229,7 +1247,11 @@ __metadata: dependencies: "@biomejs/biome": "npm:^2.4.13" "@changesets/cli": "npm:^2.31.0" + "@types/json-logic-js": "npm:^2" "@types/node": "npm:^25.6.0" + json-logic-js: "npm:^2.0.5" + json-rules-engine: "npm:^7.3.1" + rule-engine-js: "npm:^1.0.7" tshy: "npm:^4.1.1" typedoc: "npm:^0.28.19" typedoc-plugin-markdown: "npm:^4.11.0" @@ -1406,6 +1428,13 @@ __metadata: languageName: node linkType: hard +"@types/json-logic-js@npm:^2": + version: 2.0.8 + resolution: "@types/json-logic-js@npm:2.0.8" + checksum: 10c0/b1fc0b39242b8f1f939c86f47bfda213e1eb57686ee4dfbe11057df88fad0dbe0abc3582b72429975e8fb07b0267959d98341e5079ba945345931973538d2f43 + languageName: node + linkType: hard + "@types/linkify-it@npm:^5": version: 5.0.0 resolution: "@types/linkify-it@npm:5.0.0" @@ -2031,6 +2060,13 @@ __metadata: languageName: node linkType: hard +"clone@npm:^2.1.2": + version: 2.1.2 + resolution: "clone@npm:2.1.2" + checksum: 10c0/ed0601cd0b1606bc7d82ee7175b97e68d1dd9b91fd1250a3617b38d34a095f8ee0431d40a1a611122dcccb4f93295b4fdb94942aa763392b5fe44effa50c2d5e + languageName: node + linkType: hard + "comma-separated-tokens@npm:^2.0.0": version: 2.0.3 resolution: "comma-separated-tokens@npm:2.0.3" @@ -2262,6 +2298,13 @@ __metadata: languageName: node linkType: hard +"eventemitter2@npm:^6.4.4": + version: 6.4.9 + resolution: "eventemitter2@npm:6.4.9" + checksum: 10c0/b2adf7d9f1544aa2d95ee271b0621acaf1e309d85ebcef1244fb0ebc7ab0afa6ffd5e371535d0981bc46195ad67fd6ff57a8d1db030584dee69aa5e371a27ea7 + languageName: node + linkType: hard + "expect-type@npm:^1.3.0": version: 1.3.0 resolution: "expect-type@npm:1.3.0" @@ -2436,6 +2479,13 @@ __metadata: languageName: node linkType: hard +"hash-it@npm:^6.0.0": + version: 6.0.1 + resolution: "hash-it@npm:6.0.1" + checksum: 10c0/b5abe8f6f3d3040522ba0ecb64a34eda7de653bae6db19bb260dad2eeafe1b0be5e88dc57a7200d2ed2f6537dd9549597950cde6424e0dac31cfea438b49ec13 + languageName: node + linkType: hard + "hast-util-to-html@npm:^9.0.4": version: 9.0.5 resolution: "hast-util-to-html@npm:9.0.5" @@ -2586,6 +2636,32 @@ __metadata: languageName: node linkType: hard +"jsep@npm:^1.4.0": + version: 1.4.0 + resolution: "jsep@npm:1.4.0" + checksum: 10c0/fe60adf47e050e22eadced42514a51a15a3cf0e2d147896584486acd8ee670fc16641101b9aeb81f4aaba382043d29744b7aac41171e8106515b14f27e0c7116 + languageName: node + linkType: hard + +"json-logic-js@npm:^2.0.5": + version: 2.0.5 + resolution: "json-logic-js@npm:2.0.5" + checksum: 10c0/c80d96a9f704dac2f4488c7119d9c94cbf67adbd93cb47eaa5b7eadc4947f18ed6d62fd5555f245cc2f87525f9e8d7bd5f70bd9e7fba2c70366e63bd68010f23 + languageName: node + linkType: hard + +"json-rules-engine@npm:^7.3.1": + version: 7.3.1 + resolution: "json-rules-engine@npm:7.3.1" + dependencies: + clone: "npm:^2.1.2" + eventemitter2: "npm:^6.4.4" + hash-it: "npm:^6.0.0" + jsonpath-plus: "npm:^10.3.0" + checksum: 10c0/2429358d7425232a2ccb830d0d3137e17c2b44218f772316efb98b9170945d1ae269798dd9f7af484b4b559e153d3c1de0a374dd3b41af58b0407171852b5cfe + languageName: node + linkType: hard + "jsonc-simple-parser@npm:^3.0.0": version: 3.0.0 resolution: "jsonc-simple-parser@npm:3.0.0" @@ -2607,6 +2683,20 @@ __metadata: languageName: node linkType: hard +"jsonpath-plus@npm:^10.3.0": + version: 10.4.0 + resolution: "jsonpath-plus@npm:10.4.0" + dependencies: + "@jsep-plugin/assignment": "npm:^1.3.0" + "@jsep-plugin/regex": "npm:^1.0.4" + jsep: "npm:^1.4.0" + bin: + jsonpath: bin/jsonpath-cli.js + jsonpath-plus: bin/jsonpath-cli.js + checksum: 10c0/500ace17c7b8d084f9e1284e96761722600909b8ddc1f3a5b18f9152ad9e1d63a61e3d713abd6d7141d4b61e1f632f1eb67b57be6a220b17b215b95ba050af07 + languageName: node + linkType: hard + "lightningcss-android-arm64@npm:1.32.0": version: 1.32.0 resolution: "lightningcss-android-arm64@npm:1.32.0" @@ -3442,6 +3532,13 @@ __metadata: languageName: node linkType: hard +"rule-engine-js@npm:^1.0.7": + version: 1.0.7 + resolution: "rule-engine-js@npm:1.0.7" + checksum: 10c0/6cc975b52dc670f67a7332f84111902cee8b3d612a7ff99204e5b453459234fc158ac8a96f97087e7c652c5c4034026e5000bba6ae23bdfd495d7add570ef4a9 + languageName: node + linkType: hard + "run-parallel@npm:^1.1.9": version: 1.2.0 resolution: "run-parallel@npm:1.2.0" From 415d4ec110b933052260c530e42949514d3da8c8 Mon Sep 17 00:00:00 2001 From: Sebastian Dieguez Date: Mon, 22 Jun 2026 21:35:44 -0300 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- tests/contracts/benchmark-contract.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/contracts/benchmark-contract.test.ts b/tests/contracts/benchmark-contract.test.ts index 2d3442c..47c1c71 100644 --- a/tests/contracts/benchmark-contract.test.ts +++ b/tests/contracts/benchmark-contract.test.ts @@ -17,6 +17,7 @@ const requiredFields = [ 'node_version', 'package_version', 'commit_sha', + 'result_kind', ]; const requiredEngines = [ @@ -42,12 +43,12 @@ function readJson(path: string) { describe('benchmark result-data contract', () => { it('publishes methodology, JSON schema, and placeholder sample data files', () => { expect(existsSync('docs/benchmarks/methodology.md')).toBe(true); - expect(existsSync('docs/benchmarks/results.schema.json')).toBe(true); + expect(existsSync('docs/public/benchmarks/results.schema.json')).toBe(true); expect(existsSync('benchmarks/sample-results.placeholder.json')).toBe(true); }); it('defines every NJS-GROWTH-07 metric with a stable type, unit, and source note', () => { - const schema = readJson('docs/benchmarks/results.schema.json'); + const schema = readJson('docs/public/benchmarks/results.schema.json'); const resultProperties = ((schema.properties as Record).results as Record).items as Record; const properties = resultProperties.properties as Record>; const required = resultProperties.required as string[]; @@ -70,7 +71,7 @@ describe('benchmark result-data contract', () => { it('documents the complete competitor, scenario, and input-size matrix', () => { const methodology = readFileSync('docs/benchmarks/methodology.md', 'utf8'); - const schema = readFileSync('docs/benchmarks/results.schema.json', 'utf8'); + const schema = readFileSync('docs/public/benchmarks/results.schema.json', 'utf8'); for (const engine of requiredEngines) { expect(methodology).toContain(engine); From e39e7c7bc45de680f787100f48d04591b80ca03e Mon Sep 17 00:00:00 2001 From: Sebastian Dieguez Date: Mon, 22 Jun 2026 21:53:07 -0300 Subject: [PATCH 3/3] fix: move benchmark schema to public dir and require result_kind Applies the remaining code-review changes that the test suite already expected but the source did not satisfy: - Move results.schema.json into docs/public/benchmarks/ so VitePress serves it at /neuron-js/benchmarks/results.schema.json (matching its $id); previously it lived in a content dir and was never served and the contract test could not find it. - Add result_kind to the per-row required array in the schema. - Update path references in methodology.md and benchmarks/README.md, and fix the index.md link to the served public URL. Fixes the failing CI quality job (3 benchmark-contract tests). Co-Authored-By: Claude Opus 4.8 --- benchmarks/README.md | 2 +- docs/benchmarks/index.md | 2 +- docs/benchmarks/methodology.md | 8 ++++---- docs/{ => public}/benchmarks/results.schema.json | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) rename docs/{ => public}/benchmarks/results.schema.json (99%) diff --git a/benchmarks/README.md b/benchmarks/README.md index e01d83a..87140f5 100644 --- a/benchmarks/README.md +++ b/benchmarks/README.md @@ -4,6 +4,6 @@ This directory contains benchmark data artifacts for NJS-GROWTH-07. - `sample-results.placeholder.json` is deterministic placeholder data for chart and playground wiring. - It is not benchmark output and must not be used for public performance claims. -- Real benchmark output must match `docs/benchmarks/results.schema.json` and set `result_kind` to `actual_benchmark`. +- Real benchmark output must match `docs/public/benchmarks/results.schema.json` and set `result_kind` to `actual_benchmark`. See `docs/benchmarks/methodology.md` for the competitor, scenario, input-size, and metric contract. diff --git a/docs/benchmarks/index.md b/docs/benchmarks/index.md index 563ae04..cba4689 100644 --- a/docs/benchmarks/index.md +++ b/docs/benchmarks/index.md @@ -7,7 +7,7 @@ This section is a design and generation foundation. It does not publish benchmar ## Files - [Benchmark methodology and result contract](./methodology.md): competitor set, scenario matrix, input-size matrix, metric definitions, and placeholder-data policy. -- [Result JSON schema](./results.schema.json): machine-readable contract for benchmark output and downstream chart data. +- [Result JSON schema](/benchmarks/results.schema.json): machine-readable contract for benchmark output and downstream chart data. - [Visual proof system](./visual-proof-system.md): palette, typography, composition, diagram style, chart rules, social-card constraints, and README proof strip guidance. - [Visual proof prompt kit](./prompt-kit.md): reusable prompts for benchmark infographics, explainability trace diagrams, playground README GIF storyboards, AI-rule safety carousels, and README proof strips. - [Asset folder recommendation](./assets/): recommended `docs/benchmarks/assets/` structure and data-integrity rules. diff --git a/docs/benchmarks/methodology.md b/docs/benchmarks/methodology.md index b4142ef..409c5a9 100644 --- a/docs/benchmarks/methodology.md +++ b/docs/benchmarks/methodology.md @@ -16,7 +16,7 @@ The harness/result contract covers exactly these engines for the first public pr | Hand-coded TypeScript | `hand-coded-typescript` | Baseline for direct conditional logic without engine overhead. | | rule-engine-js | `rule-engine-js` | Smaller modern competitor selected because it installs/builds in this repository. | -`rulepilot` remains an alternate candidate only if `rule-engine-js` becomes infeasible later. Do not mix both in the same first chart set without updating `docs/benchmarks/results.schema.json`. +`rulepilot` remains an alternate candidate only if `rule-engine-js` becomes infeasible later. Do not mix both in the same first chart set without updating `docs/public/benchmarks/results.schema.json`. ## Scenario matrix @@ -37,7 +37,7 @@ The harness/result contract covers exactly these engines for the first public pr ## Stable result fields -Every result row must contain these fields. Units and source definitions are duplicated in `docs/benchmarks/results.schema.json` for machine consumers. +Every result row must contain these fields. Units and source definitions are duplicated in `docs/public/benchmarks/results.schema.json` for machine consumers. | Field | Unit | Source | | --- | --- | --- | @@ -79,14 +79,14 @@ A future executable harness should: 3. Execute `smoke`, `small`, and `medium` profiles by default; gate `large` behind an explicit flag. 4. Measure cold start separately from warm throughput. 5. Measure validation and explanation overhead as delta timings against the same scenario/input profile. -6. Emit JSON matching `docs/benchmarks/results.schema.json`. +6. Emit JSON matching `docs/public/benchmarks/results.schema.json`. 7. Set `result_kind: "actual_benchmark"`, `is_placeholder: false`, and `claims_allowed: true` only for real measured output. ## Visual asset consumers The first visual asset bundle can safely bind to these paths: -- Schema: `docs/benchmarks/results.schema.json` +- Schema: `docs/public/benchmarks/results.schema.json` - Placeholder sample: `benchmarks/sample-results.placeholder.json` - Methodology: `docs/benchmarks/methodology.md` diff --git a/docs/benchmarks/results.schema.json b/docs/public/benchmarks/results.schema.json similarity index 99% rename from docs/benchmarks/results.schema.json rename to docs/public/benchmarks/results.schema.json index 51c1a08..197052c 100644 --- a/docs/benchmarks/results.schema.json +++ b/docs/public/benchmarks/results.schema.json @@ -70,7 +70,8 @@ "explanation_overhead_ms", "node_version", "package_version", - "commit_sha" + "commit_sha", + "result_kind" ], "properties": { "engine": {