EXPERTA Specification
Draft for review · version 6

Design Specification

EXPERTA

A web tool that makes two-level fractional factorial designs from a request in plain language. A language model translates the request. The R package FrF2 makes the design in the browser.

Version
8, dated 2026-10-19. Version 7 is dated 2026-10-19. Version 6 is dated 2026-10-17. Version 5 is dated 2026-10-17. Version 4 is dated 2026-10-16, version 3 is dated 2026-10-16, version 2 is dated 2026-10-15 and version 1 is dated 2026-10-14. Version 2 applies the review decisions R1 to R17. Version 3 applies R18 to R23, from the review by Alan R. Vazquez. Version 4 records the decisions of the Milestone 3B plan (2026-10-16-m3b-interface-plan.md, P1 to P20). Version 5 records the decisions of the Milestone 3C plan (2026-10-17-m3c-exports-plan.md, C1 to C18). Version 6 records the decisions of the alpha release (2026-10-17-alpha-release-design.md, A1 to A18, and 2026-10-17-alpha-release-plan.md, AP1 to AP14). Version 7 adds the planned Phase 4 (Section 1.9: other design families through DoE.base and DoE.wrapper, the author's request of 2026-10-19). The report print redesign (2026-10-19-report-print-plan.md, R1 to R13) adds its changes to version 7. These changes are the print rules and the report sections in Section 8.3. They also include the clarification layout in Section 7.5 and the print row limit in Section 9.3. Version 8, dated 2026-10-19, records the alpha review by Alan R. Vazquez and its fixes (2026-10-19-alpha-review-fixes-plan.md, F1 to F14).
Status
Draft for review
Maintained by
Alan R. Vazquez (Tecnológico de Monterrey) and Fadel M. Megahed (Miami University)
Drafted with
Claude Code 2.1.299 (version 1), 2.1.300 (version 2) and 2.1.302 (version 3), model Claude Opus 5.5 (claude-opus-5-5), effort xhigh for versions 1 and 2
Writing style
About 80% ASD-STE100 Simplified Technical English. The idea to write in STE came from a post by Andrej Karpathy.
Decision logs
2026-10-14-spec-review-decisions.md (R1 to R17) and 2026-10-16-spec-review-decisions-v3.md (R18 to R23)

1Purpose and scope

1.1 Goal

The tool makes two-level fractional factorial designs from a request in plain language.

  • A large language model (LLM) translates the request into a typed specification ("spec").
  • The R package FrF2 makes the design. FrF2 runs in the browser through WebR (R compiled to WebAssembly).
  • The tool shows the design table, the resolution, the word length pattern (WLP), the minimum aberration (MA) status, the number of clear two-factor interactions (2FIs) and the factors that have all 2FIs clear (if any).
  • The LLM never makes the design. The LLM only translates.

1.2 Users

  • Quality engineering practitioners.
  • Design of experiments (DoE) researchers.
  • The tool is public. Users do not sign in.

1.3 Two roles of the tool

  1. A public tool for practitioners.
  2. A research artifact for a paper. The paper measures the accuracy of the translation step.

1.4 Success criteria

  1. Construction is exact. Each design is the design that FrF2 makes for the confirmed spec. Tests prove this (Section 11).
  2. Properties are correct. The tool computes the resolution and the WLP from the design matrix. Three independent sources must agree (Section 7.6).
  3. The tool does not claim more than FrF2 guarantees. The guarantee statement comes from a reviewed table (Section 7.7).
  4. Translation accuracy is measured. A benchmark with a frozen test set measures it (Section 12).
  5. The user confirms the spec before R runs. No design appears without this confirmation.
  6. Data stay on the device. Only the request text leaves the device during design work. In Phase 2, chart data leave the device only after the user opts in.
  7. The tool is accessible. It meets WCAG 2.1 AA (Section 9.10).

1.5 Phases

Phase Content
1 Core regular designs: runs, factors, resolution, factor names and levels, randomization with a seed, replications, center points. Projects stored on the device. Exports. The introduction video in English and Spanish. The paper evaluation, with single-model and ensemble arms.
2 Local analysis for core designs: upload of responses (Excel round trip), effects table, half-normal (Daniel) plot with Lenth's method, main effect plot, interaction plot, alias-aware linear model. FrF2 functions run in WebR. An optional AI explanation of a chart. It is off by default, and the user must turn it on.
3 Blocking, split-plot and hard-to-change factors, user-given generators, choice of fraction, and foldover as an action on a saved project ("Augment this design"). Each family gets its own benchmark slice.
4 (planned) Other design families through DoE.base and DoE.wrapper (Section 1.9): general full factorials and mixed-level orthogonal arrays, central composite and Box-Behnken designs, Latin hypercube designs and D-optimal designs. A feasibility spike in WebR comes first.
Later (not planned) Plackett-Burman designs. They are non-regular. The report, the guarantee statement and the alias display need different theory (partial aliasing, generalized resolution) and a new benchmark slice. Estimable 2FIs (a list of 2FIs that the design must keep estimable): review decision R21 moves them here from Phase 3. In Phase 1, the clear 2FIs in the report and the factor order (Section 9.6) give the user part of this control.

1.6 Scope rule

  • If a request does not fit what a two-level fractional factorial can do, the tool says that the request is outside its scope.
  • The tool does not recommend a different approach.
  • If a request is a two-level fractional factorial feature that this version does not support, the tool says "This version does not support {feature}."
  • For required estimable interactions, the message adds: "Step 3 lists the clear two-factor interactions (2FIs). To change which factors have them, change the factor order in step 2." (R22). This request is in scope, so the first rule does not apply to it.
  • Both messages come from fixed templates. The LLM does not write these messages.

1.7 Supported browser

  • The tool is tested in desktop Google Chrome. The end-to-end tests run in Chromium.
  • Other browsers get a short notice. The notice does not block the tool.
  • Reason: ChatISA found a CodeMirror problem with NVDA in Firefox (issue #10, open, cause upstream). Phase 1 has no code editor. The R code view is a highlighted <pre> block, so this problem does not apply to Phase 1.

1.8 Principles of two-level fractional factorial designs

Two-level fractional factorial designs add three principles to the classical principles of experimentation (randomization, blocking and replication). The text comes from Alan R. Vazquez (review decision R20). The text of effect heredity follows his answer of 2026-10-19 (decision F8).

  • Effect hierarchy. Low-order effects are more likely to be active than high-order effects. Main effects and 2FIs are usually more important than interactions of three or more factors. Thus, the evaluation of a two-level fractional factorial design usually does not look at interactions of three or more factors.
  • Effect sparsity. Only a few effects (main effects or 2FIs) are active. An active effect has a larger absolute size than the noise.
  • Effect heredity. Strong heredity: an interaction is more likely to be active if the main effects of all its factors are active. Weak heredity: an interaction is more likely to be active if the main effect of one of its factors is active.

Wu and Hamada (2021, Section 4.6) state the three principles. Box and Meyer (1986) is the source of effect sparsity, and Hamada and Wu (1992) of effect heredity. Published studies show that the principles hold in practice (Li, Sudarsanam and Frey, 2006; Ockuly et al., 2017). Alan R. Vazquez confirms this list (decision P4 of the Milestone 3B plan).

How the tool uses the principles:

  • Phase 1 follows the hierarchy principle, as FrF2 does. The report shows the aliasing among main effects and 2FIs, the number of clear 2FIs and the factors with all 2FIs clear (Section 7.5). The WLP still counts words of every length (Section 7.6), because minimum aberration is defined on the full WLP.
  • Phase 2 uses sparsity and heredity in the analysis. Lenth's method and the half-normal plot assume effect sparsity. The alias-aware linear model can use heredity to select among aliased 2FIs. The Phase 2 plan sets the rules.
  • The glossary (Section 9.5) has entries for effect hierarchy, effect sparsity, effect heredity and clear 2FI. Claude drafted them in Milestone 3B. Alan R. Vazquez reviewed them on 2026-10-19 (Section 9.5).

1.9 Planned extension: other design families (Phase 4)

On 2026-10-19 Fadel M. Megahed asked to plan more design families through DoE.wrapper. Ulrike Grömping, the author of FrF2, also maintains DoE.base and DoE.wrapper. These packages return the same R class design, with the same design.info record. They share most argument names: factor.names, default.levels, randomize, seed, ncenter and blocks. So one translation pipeline and one report helper can grow one family at a time.

Facts (measured on 2026-10-19). The WebR package index for R 4.6 (repo.r-wasm.org) has DoE.wrapper 0.13 and all its dependencies. Seven packages are new to the app; the others are already in the runtime.

Package Version Use Size (bytes)
DoE.wrapper 0.13 (2025-04-26) The family functions 150,672
rsm 2.10.6 Central composite and Box-Behnken designs 840,268
estimability 2.0.0 Needed by rsm 324,245
lhs 1.3.0 Latin hypercube designs 291,211
DiceDesign 1.10 Space-filling designs and their criteria 260,294
AlgDesign 1.2.1.2 D-optimal designs (Federov exchange) 514,185
Rcpp 1.1.2 Needed by lhs 2,087,828

The new packages add about 4.5 MB to the 25.3 MB of R packages that the app loads now. RcmdrPlugin.DoE and mixexp are not in the WebR index.

Families. Each family gets its own spec schema, R template, property report, post-checks, claim statement and benchmark slice, as the Phase 3 families do.

Family R function Phase 1 scope category it covers Properties that the report computes Claim
General full factorials and mixed-level orthogonal arrays DoE.base::fac.design, DoE.base::oa.design more_than_two_levels, mixed_levels Generalized word length pattern (DoE.base::GWLP), generalized resolution, orthogonality strength Only what DoE.base computes; an optimality claim needs a reviewed source (as Section 7.7).
Central composite designs DoE.wrapper::ccd.design response_surface_modeling The cube is an FrF2 design, so the Phase 1 checks apply to it; the axial distance; center points; the rank of the full quadratic model matrix The cube carries its Phase 1 statement.
Box-Behnken designs (3 to 7 factors) DoE.wrapper::bbd.design (rsm) response_surface_modeling Center points; the rank of the full quadratic model matrix A fixed published design; no optimality claim.
Latin hypercube and space-filling designs DoE.wrapper::lhs.design (lhs, DiceDesign) computer_experiment The Latin hypercube property (one point in each stratum of each factor); the maximin distance; the discrepancy "Found by a search with the seed {seed}"; never "optimal".
D-optimal designs DoE.wrapper::Dopt.design (AlgDesign) optimal_design The rank of the model matrix; the D-efficiency lower bound that AlgDesign reports "Found by the Federov exchange search"; never "optimal". The package calls this function "still somewhat experimental", so this family comes last.

Mixture designs and adaptive designs stay out of scope. DoE.wrapper::ccd.augment (a star portion added to a saved two-level design) joins "Augment this design" of Phase 3: screening first, then a response surface.

Routing rule (recommended). The family must not weaken the chain of Phase 1: the LLM extracts, rules decide, the user confirms, R computes and checks verify.

  1. A request comes in one of two forms. A practitioner names the design ("central composite", "Latin hypercube"), or describes the problem and its limits. The model-facing schema gets one field, family, for a named design.
  2. For a described problem, the voters extract the inputs of a decision table: the number of levels of each factor, quantitative or qualitative factors, the run budget against the size of the full factorial, the goal (screening, a curvature check, a quadratic model, a computer simulation) and the constraints. The table maps the inputs to a family. Example: two-level factors and a run budget below the full factorial give a regular fractional factorial (Phase 1). Alan R. Vazquez reviews the table. The LLM does not choose a family by its own judgment.
  3. A request with no named family and no trigger gets a clarification question. The question lists the families as fixed choices, with one fixed sentence each.
  4. The family is a field of the card, with its source and its agreement flag. The user confirms it in step 2, as every other field.
  5. The scope rule (Section 1.6) stays: the tool does not recommend a different approach. A family that the version does not have gets the fixed message "This version does not support {feature}."

The alternative is to let the LLM grade which family fits the request best. That is design advice from the model. Its errors are hard to see on the card, and the evaluation cannot give it a gold label without a rule. So this specification does not plan it.

Order and gate. Before a Phase 4 plan, a feasibility spike runs each family function in WebR 0.6.0 and in native R with the same seed. It compares the designs (the differential tests of Section 11). The order follows the risk: general factorials and orthogonal arrays first (DoE.base is in the runtime now), then central composite and Box-Behnken designs, then Latin hypercube designs, then D-optimal designs. The app loads the packages of a family only when the confirmed family needs them, so the start of a two-level design does not change. Section 7.9 measures the start again before a release.

Effect on the evaluation (Section 12). The Phase 1 benchmark (S1 to S9) stays as a frozen version, so its results stay comparable. Phase 4 adds slices:

  • A routing slice: requests of each family, with boundary pairs. "Check for curvature" stays a two-level design with center points. "Fit a quadratic model" goes to the response surface families.
  • One slice for each family: spec fields, design equivalence by the rules of the family, and the claim statement.
  • New metrics: the family confusion matrix, the silent error rate of each family (still the main safety metric) and the rate of a wrong family without a flag.
  • Gold families come from the team and the decision table, reviewed by Alan R. Vazquez. Jev's questions cover two-level designs only. Its scope category can be an independent vote on the family; the spike measures if it helps.

Comparison with RcmdrPlugin.DoE. The same author offers RcmdrPlugin.DoE, an R Commander plugin with menus for DoE.base, FrF2 and DoE.wrapper.

  • It needs a local R installation, R Commander and the packages in a given order. The author's page (read on 2026-10-19) calls it "still in beta shape" and advises users of the GUI to be "particularly cautious". Linux users are "partly on your own".
  • It cannot run in the browser: it is not in the WebR index, and R Commander needs Tcl/Tk.
  • EXPERTA needs no installation: the same packages run in WebR in the browser. A request in plain language replaces the menu choices. The card shows the sources and the agreement flags, and the user confirms each field.
  • The report computes the properties, and the checks fail closed. The exported R script runs in any R, including R Commander, so the two tools work together.
  • RcmdrPlugin.DoE has more options today (blocking, split-plot designs and all wrapper functions), runs at native speed and has analysis menus. It needs no network and no LLM cost for the design step.

2How this specification was made

2.1 Process

This specification came from one session in Claude Code, an AI agent that works in a terminal. It reads and writes files and runs commands with the user's approval. The model was Claude Opus 5.5 at the "xhigh" effort level. The agent loaded the brainstorming skill from the superpowers plugin, version 6.4.1. A skill is a packaged set of instructions for one kind of task. This skill sets the order of work: read the project, ask one question at a time, compare two or three approaches, present the design in sections, write the spec, review it, and get approval before any code. First, three research subagents worked in parallel. A subagent is a separate agent for one task, and it returns a written report. They read the two papers in refs/, the FrF2 2.3-5 manual (with probes in native R 4.6.1) and the ChatISA code and issues. Then the agent asked nine multiple-choice questions and discussed the answers in chat. This gave twelve decisions (D1 to D12, Section 2.4). The agent wrote version 1 of this spec, checked it for gaps and contradictions, and published it as a private web page. Fadel M. Megahed reviewed the page in sixteen points. Two more subagents read the TypeSafe Jev documentation and an earlier repository that solved equation rendering. The agent drew ten mockup screens in the visual companion of the brainstorming skill, with real FrF2 output. The authors chose among the options. This gave seventeen review decisions (R1 to R17), which version 2 applies. The transcripts, the mockups, the skills and the decision log are in replication_materials/ (Section 15).

2.2 Process figure

How EXPERTA was built

Status on 2026-10-20. Times are UTC and come from the session transcripts. Links go from each event to its cell and back.

By stage

Actor0 Inputsdone1 Brainstormdone2 Spec reviewdone3 Plandone4 Buildin progress5 Evaluateplanned6 Paperplanned
People1 event1 event4 events7 events8 eventsA. R. Vazquez reviews the gold labels, the glossary and the guarantee tableBoth authors write the paper
Claude Code (Opus 5.5, xhigh)4 events4 events7 events14 eventsBenchmark harness and scoringTables and figures from the saved outputs
Subagents and tools1 event2 events4 events6 eventsThree LLM providers and TypeSafe Jev
Records in replication_materials/1 event3 eventsplans/13 eventsevaluation/Paper repository

By date

  1. Initial request. F. M. Megahed gives the request in plain language, the refs/ folder (two papers and the FrF2 2.3-5 manual) and the ChatISA repository as a model.
  2. Brainstorming skill loaded. Claude Code loads the superpowers brainstorming skill and checks the local R, Node and Python set-up.
  3. Three research subagents. Separate agents read the two papers, the FrF2 documentation (with probes in native R) and the ChatISA code and issues. They report at 18:34, 18:38 and 18:40.
  4. Design questions. Nine multiple-choice questions and discussion in chat, 18:41 to 19:23. Result: twelve decisions (D1 to D12).
  5. Specification, version 1. Seventeen sections. The agent checks it for gaps and contradictions and commits it to git.
  6. Private web page. The specification is published as a private web page for review.
  7. Sixteen-point review. F. M. Megahed reviews the page with the public replication package in mind.
  8. Two more research subagents. The TypeSafe Jev documentation and the equation-rendering repository hf_arxiv_control_charts.
  9. Ensemble decision. Build the parallel translation step; the single model and the ensemble become evaluation arms (R1).
  10. Mockup screens. Ten screens in the visual companion, 02:58 to 03:50, built on real FrF2 output. The authors choose among the options on each screen.
  11. Checks in R and Python. The alias structure of the example design, the search-path dependency of DoE.base::generators(), date-based seeds, and title-card contrast under simulated colour-vision deficiency.
  12. Decision log. Seventeen review decisions (R1 to R17), each with its evidence.
  13. Specification, version 2. The specification is revised from the decision log. This page is built from it.
  14. Implementation plan, Milestone 1. The writing-plans skill turns Section 18 into test-first tasks for the R core. A reviewer subagent runs the plan's code and finds FrF2 catalogue errors. F. M. Megahed chooses a verified errata list and approves the plan.
  15. FrF2 findings report. A reproducible check and a shareable report of the FrF2 2.3-5 catalogue problems.
  16. Milestone 1: R core. Report helper, catalogue files and native R tests. Every catalogue entry that the tool accepts agrees with its stored WLP or the verified errata, and with DoE.base::GWLP() up to 1,024 runs. Seven entries are refused.
  17. Implementation plan, Milestone 2. The writing-plans skill turns Section 18 into test-first tasks for the browser engine and the projects. Probes measure WebR 0.6.0 in Node and native R; they find the collation dependence of FrF2's alias order and an interrupt that leaves WebR unable to answer. F. M. Megahed approves the plan with a 120-second ceiling and a computing indicator during a run.
  18. Milestone 2: browser engine and projects. Next.js shell, WebR worker with a SHA-256-pinned package mirror, codegen, project storage, and differential and performance tests. WebR and native R give byte-identical reports. A Chromium test found that IDBFS needs the PostMessage channel of WebR.
  19. Implementation plan, Milestone 3A. F. M. Megahed splits Milestone 3 into three plans. Research subagents measure the four providers with live calls; they find that no model accepts a temperature and that gemini-4-argon needs billing, which F. M. Megahed enables the same day.
  20. Milestone 3A: translation service. Schema, evidence check, prompt, four voters, agreement flags, translate route, rate limit, spend caps and log. Live tests measured each LLM voter with 100 calls; F. M. Megahed set the deadline rule (40 s, the largest LLM p95) and made Jev's outcome a flag only. The tests record the fixtures for Milestone 3B.
  21. Review by Alan R. Vazquez. A. R. Vazquez marks his changes on the specification page: the name EXPERTA, the principles of effect hierarchy, sparsity and heredity, the number of clear 2FIs in place of estimable 2FIs, and purple in the palette. F. M. Megahed and Claude sort the changes by their risk to the merged work and measure the colours. Specification version 3 applies the decisions R18 to R23.
  22. Implementation plan, pre-3B review changes. F. M. Megahed and Claude turn the review decisions into a plan of five tasks before Milestone 3B. Colour measurements replace the first purple with the Dark2 purple. F. M. Megahed decides that every plan is published as a page.
  23. Pre-3B review changes. Claude carries out the five tasks in this session, test first. The tests show that FrF2 stores the string "all" for 159 catalogue entries, which the plan's code did not read. A fresh reviewer checks the whole branch and finds no critical or important issue. The full check and the full catalogue sweep pass.
  24. Implementation plan, Milestone 3B. F. M. Megahed decides four questions: a report of an older version is computed again from the spec and the seed; the build does not wait for A. R. Vazquez to confirm R23 and the purple, and a note asks him; Claude drafts the glossary, marked as a draft until he reviews it; the references are a checked list that he confirms. He also asks that the document pages use the purple accent. Subagents check five references and draft 35 glossary entries. Claude measures the FrF2 behaviour behind each pre-check and runs the code of the plan in a copy of main before the plan is published.
  25. Milestone 3B: interface. Claude gives each of the eleven tasks of the plan to a subagent, which works test first, and a fresh reviewer checks each task: storage ready for reports, the translation client, the pre-checks, the card model, the global announcer with help panels and the glossary, steps 1 to 3, the rebuild of older reports and the privacy page. The browser tests answer the translation route from the recorded fixtures, so the build makes no LLM call. A fresh reviewer checks the whole branch and finds one important issue: after an edit in step 2, step 3 shows the old design with no notice. One fix wave adds a notice for this case and eight smaller fixes. The full check passes.
  26. Implementation plan, Milestone 3C. F. M. Megahed decides that the open questions for A. R. Vazquez do not block the work, and that an alpha version goes online for him after Milestone 3C. He decides two questions of the plan: step 6 has a "Request text" check box, checked by default, for the files that people share; an imported project whose id is already on the device is kept as a copy. Claude measures in a copy of main: no axe violation on any page, 40 ms to parse the largest report, a second full download of R.wasm when the worker reads it first, and an .xlsx file that Excel opens with its hidden sheet.
  27. Milestone 3C: exports, import and report. Claude gives each of the eleven tasks of the plan to a subagent, which works test first, and a fresh reviewer checks each task: the file writers (.xlsx, .csv, .R, project file and the archive), the downloads of step 3, the project menu, import with its check in step 3, step 6 with the report file and "All files (.zip)", the engine start text and the accessibility sweep. A full-flow test runs Phase 1 from the landing page to the report, with a returning visit. The task reviews find defects that the task tests did not: a focus that dropped to the page body, an import that could reuse a taken id, and report step errors that were not announced. The specification goes to version 5 with the decisions C1 to C18. A fresh reviewer checks the whole branch and finds three important issues: a later import in the same tab, after "Delete all", gave each project a new id, the typed request came back after "Delete all", and the project name kept the first words of the request when "Request text" was unchecked. One fix wave corrects the first two, adds a note in step 6 for the third, and makes seven smaller fixes. The full check passes.
  28. Alpha release design and plan. F. M. Megahed answers the questions of the alpha release with Claude's recommendations in front of the author. The link is public with no sign-in, because the scope rule, the rate limit, the daily spend caps and the limits on the provider keys hold the cost. Vercel hosts the app at experta-doe.vercel.app (experta.vercel.app belongs to another site), with Upstash Redis for the counters and ensemble translation. A review page files each answer of the authors as a GitHub issue, and the alpha is done when every question has an answer. The Dark2 purple is settled. Claude writes the design; a fresh reader finds eight questions, which the code and Claude's calls answer. Claude then writes the plan and measures that the Lua scripts of the counters run on an in-memory Redis for the tests.
  29. Alpha release: counters, headers, review page and the first deployment. Claude gives each of the nine tasks of the plan to a subagent, and a fresh reviewer checks each task. Most tasks were written test first. In Tasks 4 and 6 the code came first, and the failing run was shown by setting the code aside. The tasks add the secret scan and the checks of the deployed site. They add the Upstash Redis counters with a keyed hash of the address, and the reservation of the spend caps before the calls. They also add the Content Security Policy and the review questions page with its GitHub issues. A fix makes "Delete all" mount step 1 again. A measurement shows that WebR needs eval in the worker, so the worker policy allows it and the page policy does not. Zod 4.6.5 probes new Function when it builds a schema, so the app runs Zod without the JIT. The task reviews find defects that the task tests did not, for example review page errors that pointed at the wrong field. A fresh reviewer checks the whole branch and finds one important issue. The Lua scripts gave Redis numbers that a host can write in exponent form. One fix wave corrects it and six smaller items. F. M. Megahed approves the first deployment. Claude creates the private repository fmegahed/experta and the Vercel project experta-doe, and the author connects them and adds Upstash. The first deployment of main has no keys. All 198 runtime files match their SHA-256. Twenty starts on the Lighthouse mobile profile take about 138 s each. The longest gap between progress messages is 1.4 s, so the stall limit becomes 5 s. The specification goes to version 6.
  30. Alpha release goes live (Checkpoint B), and the follow-ups. F. M. Megahed approves Checkpoint B. Claude adds a random salt for the rate-limit keys without printing it, the review repository and the seven labels, and deploys again. The deployed checks pass: the exact security policy, and the eleventh request in one minute gets 429 from the shared store. Pairs of requests with and without one Redis call measure the store: a median of 17 ms and a largest call of 59 ms. At the request of the author, Claude sends the GitHub token, a new review key and the four provider keys from the local .env file to Vercel through a pipe, so no value is printed. One translation through the page costs USD 0.045. The three LLMs agree, and Jev reads the request as out of scope, as measured before. The author files one smoke answer, and Claude marks it withdrawn and closes it. Auto mode blocks a read-only check of the token access, and Claude does not try again. Then, at the request of the author, Claude sets a time limit of 1 s on each Redis call (10 times the largest measured call). The Upstash client returns the text "Aborted" as a result when a plain abort signal fires, so the limit uses a signal function. Claude also corrects the count line of "Other comments" and adds a CSV export of the review answers.
  31. The public address expertadoe.app. F. M. Megahed registers expertadoe.app at Vercel and asks that it become the public address, in addition to experta-doe.vercel.app. Claude finds no host name in the app code, adds the domain to the project, and adds www.expertadoe.app as a permanent redirect to it. The domain works at once, because Vercel holds its DNS, and the deployed site check passes on the new address. The vercel.app address keeps working for the two authors, and the paper names only expertadoe.app. The domain sends no mail, so Claude adds SPF and DMARC records that reject mail in its name.
  32. The deferred minor findings of the alpha release. F. M. Megahed asks that all deferred minor findings be done. An audit finds 63 findings in the 51 ledger lines: 47 open, 11 already fixed and 5 not actionable. Eight tasks fix 46 of them. A probe shows that Chrome cannot slow the CPU of the engine worker. So the 5 s stall limit rests on trials with the worker at full speed. The author decides on that limit.
  33. The printed report is redesigned. F. M. Megahed asks for a better PDF. The sections flow, with no forced page break. The run sheet scrolls in a box on screen. In print it uses landscape pages in column blocks of a measured width, with blank Response and Notes columns. Step 6 sets a row limit. A running header and footer, the project name in the PDF name, and a section on how the specification was made are new. The citation in APA and BibTeX and the acknowledgment are also new. The final review changed the app link to open a new tab and wrapped wide word length patterns. Four reference prints (7 factors in 16 runs, 32 factors in 64 runs, a resolution III design and 4,096 runs) have 5, 12, 6 and 14 pages. The print item leaves the known issues of the review page.
  34. The alpha review by Alan R. Vazquez and its fixes. Alan R. Vazquez answers the alpha review questions in GitHub issues #7 to #65: the export reads 60 answers, and 55 count. He agrees to most regions, gives new texts for three glossary entries and asks for three references. Claude measures the open points with probes: the rank-1 ties have equal word length patterns, two defaults have a stored pattern with one split number, and the 128-run designs with 25 to 40 factors have the same pattern as the MA designs of Xu (2009). The app now makes the MA claim, or the claim for good designs, only where this evidence supports it. For 128 runs with 25 to 40 factors, it checks each design against Xu's design when it makes the design, and the claim is none if the check fails. The glossary has 33 reviewed entries and two new drafts. Four questions are asked again on the review page, and an earlier answer does not count. F. M. Megahed decides the scope of the paper: the tool up to and including the design families of DoE.wrapper.
  35. The review fixes go live. F. M. Megahed merges the project pages (pull request #66) and the review fixes into main, and Vercel deploys the app. The deploy job of the project site stays off until the switch-on. The checks on https://expertadoe.app pass: the site test with the security headers, the refusal of the review API without a key, and the MA statement in step 3 for 7 factors in 16 runs and for 30 factors in 128 runs. The design with 30 factors passes the check against the design of Xu (2009) in the browser. Claude closes the 52 review issues that the app now applies. Seven issues stay open: the earlier answers to three questions asked again, the refused FrF2 defaults and the comment on one field of application.
Source: replication_materials/process/process.json. The "By stage" view groups the events of the "By date" view by stage and actor.
  • "By date" lists the events. Each event names its stage and its actors.
  • "By stage" groups the same events by stage (columns) and actor (rows). A link goes from each event to its cell, and from each cell back to its events.
  • The paper uses the "By stage" view as a static figure.
  • People write the text of each event. The sync script (Section 15) fills the counts and the times from the transcripts. A unit test checks that each cell of "By stage" matches its events.

2.3 Terms for readers new to agentic tools

Term Meaning
Claude Code An AI agent that works in a terminal. It reads and writes files and runs commands with the user's approval.
Model and effort The language model behind the agent (Claude Opus 5.5) and how much reasoning it does on each step (xhigh).
Skill A packaged set of instructions that the agent loads for one kind of task, for example brainstorming.
Plugin A package of skills and tools, for example superpowers.
Subagent A separate agent for one task, such as reading a paper. It returns a written report.
Memory Files that keep preferences between sessions, for example "write R code as pkg::fun()".
Visual companion A local browser page of the brainstorming skill. It shows mockups and records which option the user selects.
Transcript The complete record of a session (JSONL): each message, tool call and result.

2.4 Decisions

Decisions from the brainstorming session (version 1):

# Question Decision
D1 Purpose Public tool and paper companion. Out-of-scope requests get an "outside scope" reply with no alternative.
D2 Verification of the translation step Superseded by R1: deterministic checks, user confirmation, and a parallel translation step that is an evaluation arm.
D3 Hosting Portable Node app. No sign-in. Rate limit and spend caps. Host decided later.
D4 Staging of design families Core first (Phase 1). Then analysis (Phase 2). Then blocking, split-plot and foldover (Phase 3). Plackett-Burman later. R21 moves estimable 2FIs to Later.
D5 Analysis Phase 2, for core designs.
D6 Stack ChatISA stack, trimmed: Next.js 16, React 19, Tailwind v4, Vercel AI SDK, zod.
D7 Help (? buttons) Static reviewed glossary plus sentences computed from R output. No LLM at help time. Placement: R4.
D8 Timeouts Set from measurements. Soft limit with a Cancel option. Hard limit only as a safety net.
D9 R code display The view shows the exact code that runs in the browser. Read-only in Phase 1.
D10 Isomorphic designs Phase 1: the user can change the factor order. Choice of fraction comes in Phase 3.
D11 Working title Replaced by R7.
D12 Anthropic API key Superseded by R1 and R2: Anthropic is one of the three LLM providers.

Review decisions (version 2). The decision log gives the full text and the evidence for each.

# Topic Decision Section
R1 Verification of the translation Parallel translation step: three LLMs and TypeSafe Jev. Agreement is a flag on the spec card, not a vote. Single model and ensemble are evaluation arms. A rule written before the test-set run sets the production default. 5.6, 12.4
R2 Models gpt-6.1-sol, claude-opus-5-5, gemini-4-argon, jev-1.13.0. 5.8
R3 App shell Project workspace: projects in a sidebar, step rail Describe, Confirm, Design, Responses, Analyze, Report. 9.1
R4 Help Help opens in place under the item. No Help item in the header. A remembered "Show explanations" switch. 9.5
R5 Landing page Landing page on the first visit; later visits open the last page. 9.2
R6 Wording Plain academic labels. 9.7
R7 Name "Fractional Factorial Design Translator", spelled out, until the team selects a final name. Replaced by R18. 9.8
R8 Design step Run sheet and design properties side by side. 9.4
R9 Seed Default seed is the local date as yyyymmdd. 7.3
R10 R code style pkg::fun() everywhere; no dependence on the search path. 7.1, 7.2
R11 Browser Tested in desktop Google Chrome. 1.7
R12 Foldover Phase 3, as an action on a saved project. 1.5, 5.3
R13 Exports Downloads in context, step 6 (Report) and the project menu. Excel round trip with a checksum. 8
R14 Video One video per minor or major release, chapters by step, English and Spanish. 10
R15 Configuration Keys and model ids for all providers in .env. 13.2
R16 Video title cards Warm-white field, Miami Red rule, both logos with equal weight. R19 changes the rule to the accent colour. 10.3
R17 Process figure Two linked views of one event log. 2.2

Review decisions (version 3), from the review by Alan R. Vazquez on 2026-10-16. The decision log gives the full text and the evidence for each.

# Topic Decision Section
R18 Name EXPERTA, with the subtitle "Fractional Factorial Design Translator". 9.8
R19 Colours Charts: Dark2 purple, orange, teal and gray, at most four. Interface accent: the Dark2 purple, darkened to #625d96. 9.8, 10.3
R20 Principles Effect hierarchy, sparsity and heredity. 1.8
R21 Clear 2FIs The report shows the number of clear 2FIs and the factors with all 2FIs clear. A measure only; minimum aberration stays the selection rule. Estimable 2FIs move to Later. 1.1, 1.5, 7.5, 9.4
R22 Reply for required estimable interactions The not-supported message points to the clear 2FIs in step 3 and the factor order in step 2. 1.6
R23 Full factorials All 2FIs of a full factorial are clear. 7.5

Later plans record their decisions in the plan. Milestone 3B has P1 to P20 and Milestone 3C has C1 to C18. The alpha release has A1 to A18 in its design (2026-10-17-alpha-release-design.md) and AP1 to AP14 in its plan (2026-10-17-alpha-release-plan.md). Sections 13, 14.4, 16 and 17.1 give the result.


3Background

3.1 Evidence from the collaborators' papers

  • Vazquez, Rother and Charles-Gonzalez (Quality Engineering, 2026) asked LLMs to write design tables directly.
    • Both models gave the optimal design reliably only up to about 8 factors.
    • Example: GPT-5.1 gave the MA design in 0 of 10 runs for 16 runs and 12 factors.
    • Some outputs had resolution 1 or 2. These outputs were not regular designs.
  • Ying, Vazquez and Xu (arXiv 2607.05537, 2026) showed that the order and the wording of prompt parts change LLM success a lot.
    • Example: "n runs and m factors" gave lower success than "m factors and n runs".
  • Conclusion for this tool: do not let the LLM make the design. Let FrF2 make it. Measure the translation.

3.2 Facts about FrF2 2.3-5 (measured with native R 4.6.1)

  • FrF2() ignores resolution when you also give nruns. It gives only a warning.
  • When no catalogue design meets the requested resolution, FrF2 makes a full factorial. For very large factor counts this can fail with a memory error.
  • FrF2 accepts duplicate generators without an error. The result has aliased factors.
  • Catalogue names with a running number (for example 7-3.1) are ranked by MA. Names without a running number (for example 40-29) are "good" designs and are not necessarily MA. Some sizes hold both: in 2048 runs with 28 factors, 28-17.1 is MA and 28-17 is an older design that is not MA.
  • design.info(d)$catlg.entry holds the catalogue entry. Its stored WLP gives (A1,…,AL)(A_1, \ldots, A_L), where LL is between 4 and 13 and differs between entries.
  • randomize = TRUE is the default. With seed, the run order is reproducible.
  • seed must be an integer of at most 2,147,483,647 (.Machine$integer.max). A larger value is converted to NA with a warning.
  • DoE.base::generators(d) works only when an object named catlg is on the search path. Without library(FrF2) it stops with "alias information can only be provided, if catlg is available".
  • generators() is exported by DoE.base, not by FrF2. aliases() is exported by FrF2.
  • All FrF2 dependencies exist as WebAssembly binaries for R 4.6 at repo.r-wasm.org (about 24.5 MB in total). WebR 0.6.0 contains R 4.6.0.
  • design.info(d)$nruns includes the center points; ncube holds the cube runs.
  • With center points, desnum holds real values and design.info(d)$coding holds the coding formulas.
  • Full factorials have no aliased and no catlg.entry; without center points their desnum columns are named A1, B1, ....
  • 19 catalogue entries share rank 1 with a letter suffix (41-34.1a).
  • 12 rank-1 names in 256 runs lie outside the documented MA region.
  • The catalogue has 89 entries with a wrong stored WLP, 129 with NA values in the stored WLP, 5 broken entries (fewer generators than added factors), and 2 entries with more generators than added factors (26-17.1 and 27-18.1). Each of these 2 entries stores 19 generators. FrF2 builds the design from the first 17 or 18, but design.info(d)$aliased names factors that the design does not have. The tool refuses the 5 broken entries and these 2 entries. See replication_materials/findings/.
  • The probe scripts are in replication_materials/mockups/2026-10-14-ui/source/.

3.3 Facts about TypeSafe Jev (from the documentation, read on 2026-10-14)

  • Jev is the first "System One" model of TypeSafe. It returns typed judgments and probabilities. It does not write text.
  • Question types: Choice (one of up to 255 options), Noul (the probability of "yes") and Score (a position on 2 to 10 ordered levels).
  • Most requests complete in about 100 ms. Input costs USD 0.042 per million tokens. Output is free.
  • Versions can be pinned (jev-1.13.0). The alias jev-latest moves when a new version ships.
  • Jev is not deterministic. With byte-identical requests, no label changed in 22 questions × 6 runs, but the probabilities moved by up to 0.16 (measured on 2026-10-15). TypeSafe's own test, in which the label changed on 2 of 8 Choice questions, put a random value in each request.
  • The documentation says that Jev is not a calculator and that it leans toward the first Choice option.
  • Measured: the option order moved the probabilities of borderline outcomes by up to 0.28, but not toward the first option. A lean toward the first option appeared only when no option fitted.
  • Measured on 2026-10-16: Jev judged a 7-factor request with level ranges ("temperature 150 to 200 C, pressure 1 to 3 bar, ...") as out of scope. The three LLMs gave a design request, and Jev's own number answers read 16 runs and 7 factors. Since then, Jev's outcome is a flag only (Section 5.6).
  • Inputs are not used for training. Retention for abuse monitoring is allowed. Zero retention is for enterprise customers only. The service is hosted in the United States. The SDK 0.6.0 was released on 2026-09-15. jev-1.14.0 was released on 2026-10-14 as jev-preview; on 2026-10-15, jev-latest still pointed to jev-1.13.0. The Master Customer Agreement (Sections 4.1 and 4.3) gives TypeSafe a perpetual right to derive "Telemetry", including "learnings", from requests and to process it without restriction.

3.4 ChatISA

  • ChatISA is an in-house generative AI tool for information systems education at Miami University. Its source is on GitHub. This tool reuses its stack, its WebR worker pattern, its tan and ink design tokens and its accessibility fixes. Review decision R19 replaced the accent colour and the chart palette (Section 9.8).
  • Paper: Megahed et al. (2024), arXiv:2407.15010 (Section 19).
  • The current version on GitHub (main branch, 6.10.0) is much more advanced than the version that the latest arXiv version (v2, May 2025) describes. The latest GitHub release tag is v5.0.3 (December 2025).

3.5 Facts about WebR 0.6.0 (measured on 2026-10-15)

  • FrF2 and jsonlite need 29 packages from repo.r-wasm.org (25.3 MB). The repository has .tgz files only.
  • The worker installs each package with utils::untar(..., tar = "internal"). The default method calls system(), which WebR does not have.
  • FrF2 orders its alias chains with the collation of the R session. WebR uses C; native R on Windows uses English_United States.utf8. So the report helper sorts the chains by factor position (Section 7.5).
  • webR.interrupt() stops R, but WebR 0.6.0 then does not answer. So Cancel stops the worker and starts a new one (Section 7.9).
  • In Node on Windows, WebR 0.6.0 loads R.js with a C:\ path, which Node refuses. The copy of WebR that the app serves (public/runtimes/webr/) has a one-line patch (scripts/lib/runtime-manifest.mjs) and a package.json that marks it as CommonJS, because the project is an ES module package. Browsers do not use either.
  • The report JSON of WebR and of native R 4.6.1 is byte-identical, except for the R version (replication_materials/tests/perf/m2-differential.csv). All 879 cases of the full differential set agree.
  • IDBFS is not supported under the SharedArrayBuffer channel of WebR 0.6.0 (measured in Chromium). The worker uses the PostMessage channel, which cannot interrupt R. Cancel does not need an interrupt (Section 7.9).
  • WebR does not answer a syncfs request when IndexedDB fails inside its callback. So the worker first opens a small test database (ffd-probe). If that fails, the R library stays in memory for the session.

3.6 Facts about the LLM providers (measured on 2026-10-15 and 2026-10-16)

  • gpt-6.1-sol, claude-opus-5-5 and gemini-4-argon answer with the model-facing schema of Section 5.2 as written, through the Vercel AI SDK 7 (generateText with Output.object). Each response reports the model id that answered.
  • All three providers accept the schema's unions of string and number, its number enum and its nullable object.
  • None of the three models accepts a temperature: OpenAI and Anthropic refuse it with HTTP 400, and Google ignores it.
  • The lowest reasoning settings: OpenAI reasoningEffort: "low", Anthropic effort: "low" (thinking cannot be turned off), Google thinkingLevel: "low".
  • Latency at the lowest setting, 100 calls for each LLM on 2026-10-16 (median, p95, p99): OpenAI 4.5, 7.9 and 8.4 s; Anthropic 4.1, 10.3 and 13.2 s; Google 8.1, 38.5 and 73.8 s. Jev (20 calls): 0.12, 0.22 and 0.24 s. The data are in replication_materials/tests/perf/.
  • Google's delay does not depend on the length of the answer (correlation 0.08). A quarter of its calls took more than 20 s, and 5 of 100 took more than 40 s.
  • Cost per translation (token means of the 100 calls): OpenAI about USD 0.005, Anthropic about USD 0.018, Google about USD 0.007, Jev about USD 0.0001.
  • gemini-4-argon is not on the free tier: a free-tier key gets HTTP 429 with a quota of 0. The project's key works after billing was enabled on 2026-10-15.
  • The probe scripts are in replication_materials/plans/m3a-probes/.

4Architecture

4.1 Overview

Architecture of the Fractional Factorial Design Translator Left: the browser does all design and analysis work. Describe sends the request text to the server. Confirm shows the typed result with agreement flags. Codegen writes R code, a WebR worker runs FrF2 and the report helper, and the Design, Report and Projects parts stay on the device. Right: a thin Node server applies limits and calls up to three language models and TypeSafe Jev in parallel, then returns one typed result. In Phase 2, an optional chart explanation route runs only after the user opts in. Browser: all design and analysis work, on the device 1 Describe The request in plain language, in any language 2 Confirm: the spec card (the user must confirm) Schema and evidence checks, pre-checks, agreement flags Codegen Spec to R code in pkg::fun() style, fixed templates only WebR worker (R in WebAssembly) FrF2::FrF2(), then ffd_report(): properties and post-checks 3 Design Run sheet, properties, aliasing with factor names, R code 4 Responses and 5 Analyze (Phase 2) Uploaded results; effects, plots and model with FrF2 in WebR 6 Report and files Run sheet, R script, project file, report, all files (.zip) Projects (this device only) IndexedDB holds each project: spec, seed, run sheet, results localStorage holds one pointer: the last page opened saved and opened again Node server (thin) POST /api/translate Input limits, rate limit, spend caps Mode: one model or the ensemble Parallel calls with one deadline Strict schema check; agreement flags Logs: metadata only, no request text POST /api/explain-chart Phase 2; only after the user opts in and sees the data External services OpenAI gpt-6.1-sol: full typed result Anthropic claude-opus-5-5: full typed result Google gemini-4-argon: full typed result TypeSafe jev-1.13.0: outcome class, and which number is runs, factors, and so on request text typed result + flags up to 4 calls in parallel opt-in only
Architecture. Solid boxes are Phase 1; dashed boxes come in Phase 2. Purple lines are the only data that pass between the device and the server; nothing else leaves the device. Source: replication_materials/plans/figures/architecture.svg.

4.2 Rules

  1. LLM output is data, not code. The LLM fills a typed spec. R code comes only from the codegen templates.
  2. Only the request text leaves the device during design work. The text is the request and the clarification answers. In single mode it goes to one provider. In ensemble mode it goes to up to four providers (Section 5.6). The notice names the providers of the current mode.
  3. Chart data leave the device only after an opt-in (Phase 2). A dialog shows the exact data before the first request.
  4. The LLM is optional. The user can open an empty spec card and fill it. This path also works when the API is not available or a spend cap is reached.
  5. Checks before R. Feasibility pre-checks use a catalogue summary. They stop FrF2's silent behaviours before R runs.
  6. Checks after R. ffd_report() computes the properties from the design. If a check fails, the tool does not show the design ("fail closed").
  7. One translator module. The API route and the evaluation harness use the same module. The paper measures the production code path.
  8. No R on the server. R runs only in the browser (and in native R for tests).
  9. Projects stay on the device. IndexedDB holds the projects. There are no accounts and no server storage.

4.3 Request lifecycle

  1. The user writes a request in step 1 (Describe) and selects "Interpret request".
  2. The client sends the request text and any clarification answers to POST /api/translate.
  3. The server calls the voters of the current mode in parallel, validates each result and computes the agreement flags (Section 5.6).
  4. The server returns one of four outcomes (Section 5.1) with the flags.
  5. For design_request, the client validates the spec again, runs the evidence check and the pre-checks, and shows the spec card in step 2 (Confirm).
  6. The user edits the card if necessary, resolves each flagged field, and selects "Generate design".
  7. Codegen makes the R code. The worker runs it, then runs ffd_report().
  8. Step 3 (Design) shows the results only if all post-checks pass. The project is saved on the device.
  9. If the user edits the card again, steps 6 to 8 run again. There is no LLM call.

5Translation contract

5.1 Outcomes

Outcome Meaning What the user sees
design_request The request fits Phase 1. The spec card.
needs_clarification A required value is missing or unclear. One question from the tool, with an answer field.
out_of_scope The request is not a two-level fractional factorial. Fixed template: "This request is outside the scope of this tool. This tool makes two-level fractional factorial designs with the FrF2 package. Your request needs {category}."
not_supported_in_version The request is a two-level fractional factorial feature that this version does not support. Fixed template: "This version does not support {feature}."

Both fixed messages have a ? button ("What this tool does"). The messages do not contain alternatives.

5.2 Model-facing schema

OpenAI strict structured output needs all fields present. So the model-facing schema uses nullable fields. All three providers accept its unions of string and number (Section 3.6). The server then applies a strict zod discriminated union. This is the ChatISA pattern. All three LLM providers get the same schema through the Vercel AI SDK.

TranslationResult = {
  outcome: "design_request" | "needs_clarification" | "out_of_scope" | "not_supported_in_version",
  spec: CoreSpec | null,                  // only for design_request
  clarification_question: string | null,  // one question
  scope_category: ScopeCategory | null,   // fixed enum
  evidence: { field: string, quote: string }[]
}

CoreSpec = {
  design_family: "regular",
  factors: { name: string, low: string | number, high: string | number,
             unit: string | null, quantitative: boolean }[],
  nruns: 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | null,
  min_resolution: number | null,   // integer >= 3; pre-checks test feasibility
  replications: number,     // integer >= 1, default 1
  repeat_only: boolean,     // default false
  center_points: number,    // integer >= 0, default 0
  randomize: boolean,       // default true
  seed: number | null       // null: the client sets the local date as yyyymmdd (Section 7.3)
}

Constraints that the strict zod schema applies:

  • At least one of nruns and min_resolution is not null.
  • factors.length >= 2. The number of factors is factors.length.
  • Factor names are unique and valid as R names after a fixed sanitizing rule. The rule is in lib/spec/names.ts. Accents are removed, and other letters and digits outside ASCII become their code points in hexadecimal (for example "温度" becomes X6E29_5EA6), so names in any script give distinct R names.
  • low and high are different.
  • If center_points > 0, all factors are quantitative.
  • seed, if given, is an integer from 1 to 2,147,483,647.

5.3 Scope categories (fixed enums)

  • out_of_scope: more_than_two_levels, mixed_levels, mixture, response_surface_modeling, optimal_design, computer_experiment, adaptive_design, not_a_design_request.
    • adaptive_design means designs that change while the results arrive, for example sequential optimization. Foldover is not in this category.
  • not_supported_in_version: blocking, split_plot, hard_to_change, estimable_interactions (Later, R21), user_generators, catalogue_choice, fraction_choice, alternative_criterion (for example MaxC2; minimum aberration stays the selection rule, R21), plackett_burman, foldover (Phase 3), analysis (until Phase 2).
  • Boundary rule: "check for curvature" is in scope (center points). "Model curvature" is out of scope.

5.4 Rules for the translation

  1. Do not invent a size. If the request has no run count and no resolution need, the outcome is needs_clarification.
  2. Fixed phrase rules for resolution. The prompt contains the rules. Examples:
    • "main effects not aliased with each other" -> III.
    • "main effects clear of two-factor interactions" -> IV.
    • "estimate all two-factor interactions" -> V.
  3. Defaults. If the request does not give a value, the spec uses the default. The card shows a "default" label.
  4. Default factor names. If the request gives a count and no names, the names are A, B, C, and so on (FrF2's labels: no I and no i; above 50 factors, F1, F2, ...). Default levels are -1 and +1.
  5. Any input language. The user can write in any language (for example Spanish). The interface is in English in Phase 1.

5.5 Evidence check (deterministic)

  • Each value that is not a default must have an evidence item.
  • The quote must occur in a user turn of the thread. The check normalizes case, white space and Unicode before it compares.
  • For a number field (nruns, replications, center_points, seed, factor levels), the quote must contain the number as digits or as a number word. A small number-word table covers English and Spanish.
  • For min_resolution, the quote must occur in the text. It does not need a number, because the phrase rules (Section 5.4) map words to a resolution.
  • For a factor name, the quote must contain the name.
  • For default factor names (A, B, C, ...), the quote must contain the number of factors.
  • If a value fails the check, the voter gets one repair retry. Section 5.7 gives the result when the retry also fails.
  • The card shows each quote in a "From your text" column. If the user edits a value, the column shows "Edited by you".
  • Units and the quantitative flag need no evidence item. They follow from the levels.

5.6 Parallel translation and agreement flags

The translation step can call several independent translators ("voters") in parallel. Agreement among them is a signal for the user. It is not a vote that replaces the user.

Voters

Voter What it returns
gpt-6.1-sol (OpenAI) The full typed result (Section 5.2).
claude-opus-5-5 (Anthropic) The full typed result.
gemini-4-argon (Google) The full typed result.
jev-1.13.0 (TypeSafe) Closed judgments only: (1) the outcome and the category, as Choice questions in two levels; (2) for each number field, a Choice among the candidate numbers that code finds in the request, plus "none". It asks the outcome in two option orders and averages them, and it reads the category only when the outcome needs one (Section 3.3).
  • Jev cannot write factor names or levels. These fields come from the LLMs only.
  • Code finds the candidate numbers (digits and number words). Each candidate has a label with its position and its context, so the same number can occur twice.
  • Jev needs only the request text, so it runs at the same time as the LLMs.

Agreement rule

  • The server normalizes each voter's spec (names, units, number formats) and compares the fields.
  • If all voters agree on a field, the card shows "4 of 4 agree".
  • If voters disagree on a field, the card marks the field and shows each value with its count, for example "16 runs: 3; 32 runs: 1". The user must select a value before "Generate design" is available. This is the same mechanism as "Check this value" (Section 5.7).
  • If all voters agree on the outcome, the tool continues with that outcome.
  • If the LLM voters disagree on the outcome, the tool asks one clarification question. It uses a question that an LLM voter wrote. If no voter wrote one, it uses a fixed template.
  • Jev's outcome is a flag only. If it differs from the outcome of the LLM voters, the tool continues with the LLM outcome, and the agreement flags show Jev's outcome with its count. Jev's numbers count whenever an LLM voter gave a design. Jev's category is compared only when an LLM voter also gave a category (decision of the authors, 2026-10-16).

Deadline and missing voters

  • The step has one deadline: the largest p95 of the LLM voters, rounded up to a whole 10 s. On 2026-10-16 it was 40 s, from 100 calls for each LLM voter (Section 3.6; decision of the authors). config/translate-budgets.json holds the value, and TRANSLATE_DEADLINE_MS overrides it.
  • A voter that misses the deadline is left out at once: the server does not wait for its answer and does not read a late answer.
  • A voter that misses the deadline or fails is left out. The card says "3 of 4 checked".
  • The card names each voter (OpenAI, Anthropic, Google, Jev) with its state: answered, missed the deadline, failed, or left out before the call (spend cap reached or no key) (request of the authors, 2026-10-16; Milestone 3B).
  • If fewer than two voters return a valid result, the tool shows the single result with the label "Not cross-checked".

Modes

  • TRANSLATE_MODE=single calls one LLM. TRANSLATE_MODE=ensemble calls all voters.
  • The evaluation compares the modes (Section 12.3). A rule written before the test-set run selects the production default (Section 12.4).
  • The privacy notice names the providers of the current mode (Section 13.3).

5.7 Server pipeline

  1. Apply input limits: at most 4,000 characters per turn and 3 clarification rounds.
  2. Apply the rate limit and the spend caps.
  3. Call the voters of the current mode in parallel, with the versioned prompt and the model-facing schema.
  4. Validate each LLM result with the strict zod schema and the evidence check.
  5. If an LLM result fails validation, make one repair retry for that voter. Send the validation errors to the model.
  6. If the retry fails the schema validation, or a deadline or a provider error stops it, leave that voter out. If the first answer passed the schema validation, keep the first answer, with its failed fields marked (item 7).
  7. If the retry passes the schema validation but fails the evidence check, keep the result. The card marks each failed field "Check this value". The user must edit or confirm each marked field.
  8. Compute the agreement flags (Section 5.6).
  9. If no voter returns a valid result, return "Could not interpret the request. Fill in the form yourself."
  10. Return the result with prompt_version, schema_version, jev_questions_version, the mode, the voters of the mode that were left out before the call (left_out) and the model id that each provider returned.

5.8 Prompts and models

  • The model ids come from .env (Section 13.2).
  • gpt-6.1-sol has no dated snapshot. The server logs the model id that each response returns. Live smoke tests find changes.
  • Jev is pinned to jev-1.13.0.
  • None of the three models accepts a temperature (Section 3.6). Each call uses the lowest reasoning setting of its provider, and OpenAI calls set store: false. The development set decides the final values.
  • The prompt is a versioned file. Few-shot examples come from the development set only.
  • Prompt part order is an evaluation factor, because the order changes LLM success (Ying, Vazquez and Xu, 2026).

6Feasibility pre-checks

6.1 Catalogue summary

A build-time R script (scripts/build-catalogue.R) reads FrF2's catlg in native R. It writes data/catalogue-summary.json. For each number of factors, the file holds:

  • the run sizes that the catalogue covers;
  • the highest resolution in each run size, and the entry name;
  • the smallest run size for each resolution.

6.2 Rules

Each rule has a native R test that reproduces the FrF2 behaviour that the rule prevents.

Rule Message (facts only)
nruns is a power of 2 and inside the supported limits. "{nruns} runs is not a supported run size."
nfactors <= nruns - 1 "{nruns} runs can hold at most {nruns - 1} factors."
nruns > 2^m "The full factorial for {m} factors has {2^m} runs. {nruns} runs is more than this."
nruns and min_resolution both given, and the catalogue cannot reach min_resolution. "With {m} factors in {n} runs, the highest resolution is {R}. The smallest design with resolution {r} for {m} factors has {N} runs."
Only min_resolution given, no fraction meets it, and the full factorial is inside the limits. Continue. The report says: "No fraction meets resolution {r}. FrF2 makes the full factorial ({2^m} runs)."
Only min_resolution given, and the full factorial is outside the limits. "No supported design has resolution {r} for {m} factors."
nfactors is above the catalogue (160 factors), or the rows (N+c)×r(N + c) \times r are above max_total_rows. "This version supports at most {limit} factors." or "This version supports at most {limit} rows. This design has {rows} rows."
nruns is given, and the catalogue has no entry for this number of factors in this run size (for example 40 factors in 1024 runs; FrF2 stops with "subscript out of bounds"). "This version supports at most {limit} factors in {nruns} runs." (decision P8 of the Milestone 3B plan)
The catalogue entry that FrF2 selects has the status broken (7 default sizes; FrF2 uses 26-17.1 for 26 factors in 512 runs without a message). "The FrF2 catalogue entry {entry} for {m} factors in {nruns} runs fails the checks of this tool." (decision P8)
center_points > 0 and a factor is not quantitative. "Center points need all factors to be quantitative."
  • The messages state facts. They do not tell the user what to do.
  • The performance tests set the supported limits (Section 7.9).
  • Codegen never passes nruns and resolution together to FrF2.
  • The rules are in lib/spec/precheck.ts. replication_materials/tests/fixtures/precheck-cases.json has one input for each rule: a unit test checks the messages, and a native R test checks the FrF2 behaviour (Milestone 3B).

7R execution and the property report

7.1 R code

All R code, in the app and in the exports, uses the pkg::fun() style. It contains no library() call. Example for the coating study used in the mockups:

d <- FrF2::FrF2(nruns = 16, nfactors = 7,
                factor.names = list(Temp = c(150, 200), Pressure = c(1, 3),
                                    Speed = c("slow", "fast"), Time = c(10, 20),
                                    Feed = c(0.10, 0.20), Depth = c(1, 2),
                                    Coolant = c("off", "on")),
                randomize = TRUE, seed = 20261014)
  • If the spec has nruns, the call uses nruns and nfactors. It does not use resolution.
  • If the spec has only min_resolution, the call uses nfactors and resolution.
  • The factor order in the spec sets the factor-to-column assignment.
  • The R code view shows the exact string that the worker runs. A unit test asserts this. The label is "R code".
  • The exported .R file starts with a comment block: app version, R, WebR, FrF2 and DoE.base versions, and the date.

7.2 Namespaced calls and the search path

  • Some FrF2 and DoE.base functions look up objects on the search path. DoE.base::generators(d) needs catlg there (Section 3.2). Under the pkg::fun() style, nothing is attached, so such calls fail.
  • Rule: the report helper does not call functions that need the search path. It reads the generators from design.info(d)$catlg.entry[[1]]$gen (column numbers in Yates order) and maps them to the factor names.
  • Test: every R snippet that the app runs or exports runs in a fresh R session with only the base packages attached, in native R and in WebR. The test fails on any error or warning.

7.3 Randomization and the seed

  • By default, the run order is random (randomize = TRUE).
  • The default seed is the local date of the user's device as yyyymmdd, for example 20261014. The card shows it with the label "default (today's date)".
  • The user can type another seed: an integer from 1 to 2,147,483,647. A seed from the request text needs evidence (Section 5.5).
  • The LLM never selects a seed.
  • The seed is in the R code, the exports and the project file. The project file also records the full creation time and the time zone.
  • Designs with the same number of runs made on the same day get the same run order. This is acceptable: each experiment is still randomized, and the user can change the seed.
  • If the user turns randomization off, the design uses the standard order and the R code has no seed.
  • Test: for a fixed set of seeds and designs, the run order in WebR (R 4.6.0) equals the run order in native R 4.6.1.

7.4 Report helper

  • r/ffd_report.R is the one source file. Native R tests source it. The build copies it to public/r/ for WebR.
  • ffd_report(d, spec) reads the design. It does not change the design.
  • A "How we compute this" link in the help opens the file.

7.5 Report content

Item Source
Run sheet: run order, standard order, real levels, coded levels d, DoE.base::run.order(d), DoE.base::desnum(d)
Word length pattern Computed from the design matrix (Section 7.6)
Resolution The smallest j≥1j \ge 1 with Aj>0A_j > 0 in the computed WLP (Section 7.6). If all Aj=0A_j = 0, the design is a full factorial.
Catalogue entry, for example 7-3.1 names(DoE.base::design.info(d)$catlg.entry)
Guarantee statement Guarantee table (Section 7.7)
Generators design.info(d)$catlg.entry[[1]]$gen, mapped to factor names (Section 7.2)
Alias chains for main effects and 2FIs design.info(d)$aliased (main and fi2), shown with the real factor names, in factor order (Section 3.5). The report shows two parts, "Main effects" and "Two-factor interactions". Each part has its summary sentence and a numbered list of all groups in columns.
Clear 2FIs Catalogue entry clear.2fis, mapped to the real factor names. A 2FI is clear if no main effect and no other 2FI is aliased with it; interactions of three or more factors are not taken into account (FrF2's definition; Section 1.8). A full factorial has no catalogue entry and no aliasing, so all its (k2)\binom{k}{2} 2FIs are clear (R23). The number of clear 2FIs is the length of the list.
Factors with all 2FIs clear Catalogue entry all.2fis.clear, mapped to the real factor names (report field all_2fis_clear). FrF2 stores the string "all" when every factor has all 2FIs clear (159 entries, resolution V and higher); the report then lists all factors. For a full factorial: all factors.
FrF2 warnings and messages Captured with captureConditions: true. Shown as text.
Versions R, WebR, FrF2, DoE.base, report helper, app. The report shows them in a table, with the SHA-256 of the run sheet.

In the report, the Request section shows the request text once. The turns after the first follow under "Clarification", as "Question from EXPERTA" and "Answer" (decision R2 of the report print redesign).

7.6 WLP computation

For a two-level design with NN runs and nn factors, code each level as −1-1 or +1+1. Let dabd_{ab} be the Hamming distance between runs aa and bb: the number of factors at which the two runs differ. The word length pattern (A1,…,An)(A_1, \ldots, A_n) is (Xu and Wu, 2001):

Aj=1N2∑a=1N∑b=1NKj(dab;n),j=1,…,n, A_j = \frac{1}{N^2} \sum_{a=1}^{N} \sum_{b=1}^{N} K_j(d_{ab};\, n), \qquad j = 1, \ldots, n,

where KjK_j is the Krawtchouk polynomial

Kj(d;n)=∑i=0j(−1)i(di)(n−dj−i). K_j(d;\, n) = \sum_{i=0}^{j} (-1)^i \binom{d}{i} \binom{n-d}{j-i}.

The resolution is the length of the shortest word:

R=min⁡{j≥1:Aj>0}. R = \min \{\, j \ge 1 : A_j > 0 \,\}.
  • A regular design is a coset of a linear code. A coset is distance-invariant: the distances from each run to all runs have the same distribution. So the tool uses the distances from run 1 only:
Aj=1N∑b=1NKj(d1b;n). A_j = \frac{1}{N} \sum_{b=1}^{N} K_j(d_{1b};\, n).
  • This costs O(Nn)O(Nn) operations instead of O(N2n)O(N^2 n). The general double sum stays for non-regular designs (later phases) and for tests.
  • The computation uses one replicate and the cube points only. Center points are not used.
  • For a regular design, each AjA_j must be an integer. The helper checks this within a small tolerance. If the check fails, the report fails closed.
  • Tests compare three sources for each catalogue entry within the supported limits: this computation, DoE.base::GWLP(), and the stored catalogue WLP. The comparison with the stored WLP uses the stored values that are not NA and accepts the verified errata (Section 7.8, check 6).

7.7 Guarantee table

  • scripts/build-catalogue.R puts each catlg entry into one class:
    • MA: the entry is first in an MA ranking that the FrF2 documentation calls complete.
    • catalogue_not_MA: FrF2 calls the entry "good, not necessarily MA".
    • full_factorial.
  • The script quotes the FrF2 documentation text for each rule.
  • Entries that need their own rule have more classes: rank1_tie (entries that share rank 1), rank1_outside_documented_region, ranked_not_first, stored_wlp_error and broken_entry.
  • The interface shows only the statement for the claim of the design.

The claim. The report has two strings, catalogue.claim and catalogue.claim_basis (report 1.3.0, Section 8.1). The claim comes from the class of the entry, the size of the design and the reviewed range of its region (decisions F1 to F5 of 2026-10-19-alpha-review-fixes-plan.md). The statement comes from the claim.

Claim Statement
MA Minimum aberration design from the FrF2 catalogue, entry {name}.
good Design from the FrF2 catalogue, entry {name}. FrF2 lists it as good, not necessarily minimum aberration.
full_factorial Full factorial design ({n} runs).
none, with an entry Design from the FrF2 catalogue, entry {name}.
none, without an entry Design not from the FrF2 catalogue.

The rules apply in this order. The first rule that fits sets the claim and its basis.

  1. A full factorial design gets full_factorial (basis full_factorial).
  2. An entry of class MA or rank1_tie, with a number of factors inside the reviewed range of its region, gets MA:
    • For 128 runs with 25 to 40 factors, the reference check applies (below). If the computed WLP equals the reference WLP, the basis is region_and_reference_wlp. If it differs, or the report has no WLP, the claim is none (basis reference_wlp_differs).
    • For a tie entry, the basis is region_and_equal_wlp_tie. For the other entries, it is region.
  3. The entries 21-16.1 and 22-17.1 (class stored_wlp_error) get MA (basis errata_verified).
  4. An entry of class catalogue_not_MA or rank1_outside_documented_region gets good (basis frf2_good).
  5. All other designs get none (basis none).

The reviewed ranges. Each region has a range of factors in which the tool makes the MA claim (reviewed_min and reviewed_max in data/guarantee-table.json). For 12 regions, this range is the range that Alan R. Vazquez confirmed on 2026-10-19. For the region of 128 runs with 25 to 64 factors, he confirmed 40 to 64 factors (#61). For 25 to 39 factors, he answered "Not sure". The claim for these sizes rests on decision F2 (the evidence of Xu, 2009, and the check at generation time). This question is asked again. A later review can narrow one range. The source for each region (the FrF2 manual):

Runs Factors Source
4, 8, 16, 32 1 to 3, 7, 15, 31 Complete list (Chen, Sun and Wu, 1993).
64 1 to 63 Complete for resolution IV, plus MA resolution III designs for 33 to 63 factors.
128 1 to 24 MA (Xu, 2009; Block and Mee, 2005).
128 25 to 64 MA. For 40 to 64 factors, the answer of Alan R. Vazquez (#61). For 25 to 39 factors, decision F2 (Xu, 2009, and the reference check); he answered "Not sure", and the question is asked again.
128 65 to 127 MA resolution III designs.
256, 512 1 to 36, 1 to 29 MA among resolution IV or higher (Xu, 2009; Ryan and Bulutoglu, 2010).
1024, 2048, 4096 1 to 28, 1 to 32, 1 to 26 MA only up to these numbers of factors. The other designs are good designs from Xu (2009) and Ryan and Bulutoglu (2010).

The reference check. For 128 runs with 25 to 40 factors, the report compares the WLP of the design with the WLP of the MA design of Xu (2009, Section 4; Table 9 of the preprint of 2007-09-28). r/ffd_report.R builds that design from the columns that Xu prints (FFD_XU2009_128; the function ffd_reference_wlp). It computes its WLP with the same function as the report (Section 7.6). The report passes the WLP that it computed from the cube points of the design. The two WLPs must be equal at every length. The check proves that the design has the aberration of Xu's design. It does not prove that Xu's design is MA: that rests on his complete enumeration of the odd 128-run designs of resolution IV, which exist only up to 40 factors. If the check fails, the claim is none, and the statement names only the entry (fail closed).

The other entries. Decisions F3 to F5 set the claims of the entries that the documented regions do not cover. Alan R. Vazquez is asked to confirm them (Section 14.4).

  • The 19 entries that share rank 1 (128 runs with 41, 42, 43, 44 and 50 factors) get MA. They are the only catalogue entries of their sizes, and their WLPs are equal at every length (measured from the design matrix).
  • The 223 entries without a running number (for example 29-19) and the 12 rank-1 names outside the documented region (69-61.1 to 80-72.1, 256 runs) get good.
  • 21-16.1 and 22-17.1 get MA. Their stored WLP is wrong only because one number is split in two. By the computed WLP, each has less aberration than every other entry of its size.
  • The other 87 entries with a verified stored-WLP error, the 2,443 ranked entries after the first, and the 7 refused entries get none. In all, the 3,099 catalogue entries have 327 MA, 235 good and 2,537 none.
  • The 129 entries with NA values in the stored WLP are compared on the known values only (Section 7.8).
  • The tool refuses the 5 broken entries and the 2 entries with more generators than added factors (26-17.1 and 27-18.1, the FrF2 defaults for 512 runs with 26 and 27 factors). To accept these 2 entries, the tool must recompute their aliases and clear 2FIs, and the review must check them first.

What the review found. Reviewer: Alan R. Vazquez, on 2026-10-19 (GitHub issues #7 to #65, commit a3790d3). The review block of the table has the status partial.

  1. He agreed to the sentences of the classes and to 12 of the 13 regions. He kept the bounds of the regions 1024, 2048 and 4096 (answers #57 to #60). The claim now applies in these regions. For the 13th region (128 runs, 25 to 64 factors), he confirmed 40 to 64 factors.
  2. He agreed that the claim holds with center points, replications and a request that gives only a resolution (answer #49). The claim of the selected entry stays in these cases.
  3. He was not sure about the 128-run region for 25 to 39 factors (#61), the entries without an MA claim (#63) and the glossary entry for the factors with all 2FIs clear (#46). Four questions are asked again (Section 14.4): the 128-run region, the entries without an MA claim, and the glossary entries for the factors with all 2FIs clear and for the guarantee statement.
  4. The tool still refuses 26-17.1 and 27-18.1. He is revising the FrF2 findings (#64). The question stays as it is and is not asked again. The two entries stay refused until his revision.

A software test also checks that FrF2 selects the .1 entry whenever one exists for the requested size.

7.8 Post-checks (fail closed)

The report checks the following before the tool shows the design:

  1. The number of rows equals the expected count. The formula for the expected count (runs, replications, repeat_only, center points) comes from measured FrF2 behaviour. A native R test covers each combination of these options.
  2. Number of factors = number of factors in the spec.
  3. Each factor column is balanced in the cube points.
  4. All coded values are -1 or +1 (or 0 for center points).
  5. The computed resolution is at least min_resolution, if the spec gives one.
  6. If the design has a catalogue entry, the computed WLP equals the stored catalogue WLP at each stored length that is not NA, or the entry is in the verified errata list (data/catalogue-errata.json; decision of 2026-10-15).
  7. Each AjA_j of a regular design is an integer.
  8. If the design has a catalogue entry, the entry has one generator for each added factor, and each added factor column equals the product of the base factor columns that its generator names.
  9. Each factor in the alias chains of design.info(d)$aliased is a factor of the design.
  10. If the spec gives them, repeat_only, randomize and seed equal the settings that the design stores. The worker always gives them.

A check that cannot be computed fails. Examples: a WLP that is not computed because the design has NA values, and a value of length 0 or NA.

If a check fails, the tool shows "Report check failed. The design is not shown." and the name of the failed check. It does not show a table.

7.9 Runtime

  • Pinned versions: WebR 0.6.0 (R 4.6.0), FrF2 2.3-5, DoE.base 1.2-5. A self-hosted package mirror holds the binaries. A manifest records the SHA-256 of each file.
  • scripts/setup-runtimes.mjs copies WebR from npm and mirrors the packages from repo.r-wasm.org/bin/emscripten/contrib/4.6. The replication materials keep a copy of the 29 package files (replication_materials/runtime-archive/, decision of 2026-10-15). The setup takes each file from that copy and downloads only a file that the copy does not have.
  • One module worker. The page starts the worker when it opens ("prewarm"). The worker loads WebR, checks the size and the SHA-256 of each package file, installs the packages, loads the FrF2 namespace, and sources the report helper. Before WebR starts, the worker checks that webr-worker.js, R.js and R.wasm can be loaded, so a missing file gives a stated reason.
  • IndexedDB cache. The R library is kept in IndexedDB (IDBFS). After the first visit, and after a restart of the worker, it loads from there with no download. If IndexedDB cannot be opened, the library stays in memory for the session.
  • Status. The footer shows "R engine: starting R" before the first package message, then "R engine: loading (n%)", then "R engine: preparing the R packages" after the last package byte, then "R engine: ready" (decision C3). A polite live region announces the changes.
  • Headers. COOP same-origin and COEP require-corp on the pages, the worker path and the runtime path. These headers make the pages cross-origin isolated. The worker uses the PostMessage channel of WebR, because IDBFS is not supported under the SharedArrayBuffer channel (Section 3.5). Cancel stops the worker and starts a new one, because WebR 0.6.0 does not answer after an interrupt.
  • Time budgets:
    • Engine cold start: no hard limit. A progress bar shows the bytes of the R packages. WebR's own start (R.wasm, 12.3 MB compressed) sends no progress; the footer says "R engine: starting R" (decision C3, measured). After the last package byte, the footer says "R engine: preparing the R packages" and the stall timer stops, because the save to IndexedDB and the load of FrF2 send no progress. "Retry" appears only if progress stops for a set time, counted from the first progress message.
    • Design run: from the start of the run, the footer shows "R engine: computing the design (m:ss)" and an activity bar. At the soft limit, it shows "R engine: still running (m:ss)" and a Cancel button. A hard limit (default 10 minutes, set in config) stops a worker that does not respond. Step 3 shows the same indicator and Cancel (Milestone 3B).
    • FrF2 search limits (Phase 3, for example max.time) must be less than the soft limit.
    • The soft limit is at least three times the observed p99 warm time from the performance tests. The measured values are in config/runtime-budgets.json, and the supported limits in data/supported-limits.json.

8Projects, storage and exports

8.1 Project model

A project is the unit of work. It holds:

  • the request text and the clarification turns (optional in exports: Step 6, "Request text", checked by default; decision C1);
  • the confirmed spec, the seed and the factor order;
  • the record of the interpretation: the model ids, the mode, the prompt, schema and Jev-question versions, and the time (older projects have none);
  • the R code that ran, and the versions;
  • the run sheet and its SHA-256;
  • the report values (report version 1.3.0 since 2026-10-19: the field catalogue.claim and the claim statements of Section 7.7 are new; a stored report of version 1.2.0 is made again by the rule of Section 8.2);
  • in Phase 2: the responses and the analysis settings (not images; charts are made again).

8.2 Storage on the device

  • IndexedDB holds the projects. A write is complete only when its transaction completes, and the connection closes when another tab opens a newer version of the database.
  • A stored record that matches no schema is listed in the sidebar as "cannot be opened", with Export and Delete. It is never hidden (decision P19 of the Milestone 3B plan).
  • A report with another report version is made again from the stored spec and seed in step 3. It replaces the stored report only if the new run sheet has the stored SHA-256; otherwise the stored project stays unchanged and step 3 names the versions that differ (decision P1).
  • localStorage holds two small values: a pointer to the last page opened, and the "Show explanations" switch.
  • sessionStorage keeps the unsent text of step 1 (key ffd-draft:{project id or "new"}) until the interpretation is stored (decision C15). The text comes back after a plain link and after the browser's Back button. The draft is also removed when the user fills in the form by hand ("Fill in the form yourself"), when its project is deleted, and by "Delete all".
  • All storage access is in try/catch. The tool works when storage is not available (for example in private browsing). Then projects last only for the session, and a notice says so.
  • The sidebar shows the storage use and has "Export all (.zip)", "Import project" and "Clear". "Clear" asks for confirmation in the page.
  • "Export all (.zip)" gives experta-projects-{yyyy-mm-dd}.zip. It holds one {stem}.project.json for each readable project. Names that repeat get -2, -3 (decision C8).
  • "Import project" accepts several .json and .zip files. For a .zip file, it imports every *.project.json in the archive (decision C8).
  • Each project has a disclosure button "Project actions: {name}" (aria-expanded) with four buttons: Rename, Duplicate, "Export project (.json)" and Delete. It is not an ARIA menu. Rename and Duplicate are not available for a project whose report waits for a rebuild. Delete asks for confirmation in the page (decision C10).
  • After a save, the workspace replaces the saved project in its list. It does not read all projects again (decision C5).

8.3 Exports

File Content Phase Where
Run sheet .xlsx Runs in run order, real levels, an empty response column. A hidden sheet holds the project id and the SHA-256 of the design. 1 (upload in 2) Step 3, Download
Run sheet .csv Run order, standard order, real and coded levels. UTF-8. 1 Step 3, Download
R script .R The R code in pkg::fun() style with a version header. Phase 2 adds the analysis code. 1, grows in 2 Step 3 and step 6
Project file .project.json The project (Section 8.1), validated by a versioned schema. 1, grows in 2 Project menu
Report .html One self-contained file: no external links, charts as embedded SVG. PDF comes from the browser's print, with a print style sheet. 1, grows in 2 Step 6
Chart .png, .svg, data .csv Each chart in the palette of Section 9.8, and the numbers behind it. 2 Next to each chart
All files .zip All of the above, a README in plain language, and a manifest with versions and the SHA-256 of each file. 1, grows in 2 Step 6
  • Downloads in context give single files where the user works. Step 6 (Report) gives the report and the archive of all files. The project menu renames, duplicates, exports and deletes a project. The sidebar imports projects.
  • A test checks that each file is the same from each place where it is offered.
  • Every download is announced once, politely: "Download started: {file name}."
  • The project file is { "format": "experta-project", "format_version": 1, "app_version": "...", "project": <stored record> } as UTF-8 JSON with two-space indentation and a final newline. It has no export time, so equal projects give equal files. A project whose report waits for a rebuild is exported from its stored record. Import reads the record with the store's readRecord, so a record with the current or an older report version is read (decision C7).
  • "Export project" in the project menu always gives the whole project. Without the request text (Step 6, "Request text" not checked), the report and the project file in "All files (.zip)" have no request and no clarification turns, and the project file also drops the quotes of the card: values "From your text" become interpretation values (decision C1). The project name is not part of the request text: while "Request text" is not checked, step 6 shows the note "The project name stays in the file names and in the report. To change it, rename the project."
  • The project file in "All files (.zip)" is made from the stored record, as "Export project" makes it. So the two files are equal for the same project.
  • The .csv file follows RFC 4180: quoted fields where needed, CRLF line ends, UTF-8 without a byte order mark, "NA" for a missing value, and a final line end. The columns are Run, Std, the real levels (headers with units), then the coded levels (headers "{name} (coded)") (decision C12). Values are written unchanged. A text that starts with "=", "+", "-" or "@" is not changed. The .xlsx file is the file for spreadsheet programs.
  • The .xlsx file is written as OOXML with fflate; its hidden sheet experta holds the project id, the run-sheet SHA-256, the app version, the report version and the format version (decision C6).
  • The report file is one HTML document: inline CSS, no script, one link (to the app), no external resource, system fonts (Georgia for headings, Arial for text), the accent #625d96, and a print style sheet. The page-break rule of decision C11 of the first plan (each section on a new page) is replaced by the rules below.
  • The report has these sections, in this order. Each one has a check box in step 6. A title block with the logo, the project name, the design notation and the date opens the report.
    1. Request: the request text once, then "Clarification" with the later turns.
    2. Specification: the confirmed fields.
    3. How the specification was made: the model ids of the voters and the mode. It also shows the prompt, schema and Jev-question versions and the date of the interpretation, as the card stores them. A project without these values shows "Not recorded". A specification filled in by hand says so. The card stores how it was made (translation, hand or imported), and the section decides by that value. It names the factors that the user removed or added in step 2, and says when the user changed their order.
    4. Design properties and aliasing: the word length pattern in tables of at most 10 word lengths, and the alias groups in two parts.
    5. Run sheet.
    6. R code.
    7. Versions and citation: a table of versions, the SHA-256 of the run sheet and the citation in APA and BibTeX with the link https://expertadoe.app. A toggle that uses only CSS shows one form on screen; the print shows both. The Acknowledgment closes every report, outside the numbered sections: "The API and hosting costs of EXPERTA are funded by the Raymond E. Glos Professorship in Business at Miami University, held by Fadel M. Megahed."
  • Print rules of the report (decisions R1 and R4 to R8 of the report print redesign). No script runs in the report, so these rules are in CSS only.
    • Sections flow with no forced page break. A heading stays with the text after it. A small table, a code block and an alias group do not split across pages.
    • The run sheet shows in a scroll box on screen, at most 75% of the window high. The header row and the Run column stay in view, and the rows are in groups of 256. The content-visibility property is not used. CSS containment does not apply to table row groups. The three view-time runs measured content-visibility first each time, so the run order and the effect cannot be told apart (replication_materials/tests/perf/print-layout.csv).
    • In print, the run sheet uses landscape pages. A measured width model (config/print-layout.json, packFactorBlocks) packs the factor columns into blocks that fit one page width. Each block repeats Run and Std order, and the header row repeats on each page. The last block has the blank columns Response and Notes. A page holds at least 25 rows, measured in Chromium for Letter and A4.
    • The number of rows in print is a choice in step 6 (Section 9.3). A limited print shows a note under the table. The HTML file has every row.
    • A running header and footer come from @page margin boxes with fixed app texts. The top has "EXPERTA · Design report" and the date. The bottom has "expertadoe.app · version {APP_VERSION}" and "Page {n} of {N}". Chromium and Edge print them. Other browsers print without them.
    • During print(), the app sets the page title to "{project name}: EXPERTA design report" and then restores the old title. So the PDF file name has the project name.
    • The design notation prints in the accent colour. Numbers use tabular digits. The report is the same file in the frame, in "Report (.html)" and in the archive.
    • Four reference prints are in replication_materials/findings/2026-10-19-report-print-after-*.pdf: 7 factors in 16 runs, 32 factors in 64 runs, a resolution III design, and 4,096 runs.
  • Step 6 shows the report file in an <iframe> with srcdoc. The preview frame has sandbox="allow-same-origin allow-modals allow-popups allow-popups-to-escape-sandbox". Chromium ignores print() in a sandboxed frame without allow-modals. The link to the app has target="_blank", so it opens a new tab and the frame keeps the report. No script runs in the frame, because allow-scripts is not given. "Print / PDF" prints that frame.
  • The SHA-256 of a run sheet is the SHA-256 of the UTF-8 text JSON.stringify({ labels, run, std, levels, coded }) of the report (lib/report/sha.ts, decision P12).

8.4 Round trip with responses (Phase 2)

  1. The user downloads the run sheet as Excel and runs the experiment.
  2. The user types each result into the response column. More response columns are allowed.
  3. Step 4 (Responses) reads the file. The factor columns must equal the stored design, run by run. A sorted or edited sheet fails this check, and the tool names the first row that differs.
  4. R adds the responses to the design object with DoE.base::add.response().

8.5 Import

  • The tool validates the project file with its schema.
  • The tool makes the design again from the spec and the seed, and compares the SHA-256 with the stored run sheet.
  • If they are equal, the tool shows "Project imported. The rebuilt design matches the stored run sheet (SHA-256)."
  • If they differ (for example after an FrF2 update), the tool keeps the stored run sheet, because that is the design that was run. It shows the versions that differ. When no version differs, the list has one item: "None. The stored R, webR, FrF2 and DoE.base versions equal the current versions."
  • The check runs in step 3 of the imported project, in the session of the import (decision C9). Step 3 checks only an imported project that has a stored report, or that waits for a rebuild. A project with a spec and no report makes its first design as usual.
  • The check never changes the stored record. A project that waits for a rebuild follows the rebuild rule of decision P1, with "Project imported. " before its text.
  • A project with a spec and no card gets a card from its spec. The origin of its values is imported, and the label is "From the project file" (decision C9).
  • An imported project whose id is already on the device gets a new id and the name "{name} (imported)". A file never overwrites a stored record. The ids that are already taken are the listed projects, the records that cannot be opened, and the files read earlier in the same selection (decision C2).
  • Each import has one announcement: polite for the count only, and assertive when a file failed.
  • The file input ("Import project", several files, .json,.zip) is cleared after each read.

9User interface

The mockups for this section are in replication_materials/mockups/2026-10-14-ui/. Each screen has a standalone HTML file, the source fragment, a PNG and the options that the authors selected.

9.1 Workspace layout

  • Header: the two logos, the name and the current project. There is no Help item in the header.
  • Sidebar: "New design", the projects on this device (name, design, size, date) and the storage controls. At narrow widths the sidebar becomes a menu.
  • Step rail: 1 Describe, 2 Confirm, 3 Design, 4 Responses, 5 Analyze, 6 Report. Steps 4 and 5 are visible but marked "Phase 2" until Phase 2 ships.
  • Footer: Home, Glossary, Architecture, Paper, the version and the R engine status.
  • Phase 3 adds options to step 2 (blocking, split-plot, generators) and "Augment this design" (foldover) to step 3. The layout does not change.

9.2 Landing page and later visits

  • The first visit to / shows the landing page: a short description, the introduction video, "Start a design", and three blocks titled "Maintained by", "Privacy" and "Citation". The landing page replaces a separate About page.
  • On later visits to /, a small script in the page head reads the pointer in localStorage and opens the last page before the page is drawn.
  • The logo and "Home" go to /?home. This address always shows the landing page.
  • Without storage, every visit shows the landing page.

9.3 Steps

Step Content
1 Describe The request field, example requests, "Interpret request", "Fill in the form yourself", and the privacy notice for the current mode.
2 Confirm The spec card: factors (with order controls), runs, minimum resolution, replications, center points, randomization and seed. Each value shows its quote ("From your text"), a "default" label, an "Edited by you" label, a "From the project file" label (decision C9), or an agreement flag.
3 Design Section 9.4.
4 Responses (Phase 2) Upload of the run sheet with results, and the checks of Section 8.4.
5 Analyze (Phase 2) Effects, plots and model. "Explain this chart with AI" next to each chart, off by default.
6 Report Report contents (check boxes), "Rows of the run sheet in print", a preview, "Report (.html)", print to PDF, "All files (.zip)". If the record cannot be read, step 6 shows "The stored project could not be read." If the archive build fails, it shows "The archive of all files could not be made." Each message is assertive, and no file is made. "Rows of the run sheet in print" is a select with "All rows" and "First 64", "First 256" and "First 1,024". It offers only the limits below the number of rows, and each choice shows its estimated pages, counting every column block. The default is all rows for a run sheet of up to 256 rows, and the first 256 for a longer one.

9.4 Design step layout

  • The headline: 2k−p2^{k-p}, the number of runs and the resolution, then the guarantee statement.
  • Left: the run sheet. Controls: run order or standard order; real levels or coded levels; Print; Download.
  • Right: design properties: resolution, WLP, generators, the number of clear 2FIs and the list of clear 2FIs, the factors that have all 2FIs clear (if any), run order and seed, FrF2 messages, and the aliased 2FIs with the real factor names. "Clear" does not take interactions of three or more factors into account (hierarchy principle, Section 1.8).
  • Below the run sheet: "R code" (collapsed), with Copy.
  • A note says: "To change which effects are aliased, change the factor order in step 2." If some factors, but not all, have all 2FIs clear, the note also names them. Example for 9 factors in 32 runs: "Only the factor in position 9 (now Feed) has all 2FIs clear. To give this property to a different factor, move that factor to position 9 in step 2."
  • Below about 1100 px wide, the two columns stack.

9.5 Help at the ? button

  • Where: each spec card field, each design property, each step and the two fixed scope messages.
  • How: the ? button opens a panel in place, under the item. The panel pushes the content down. It covers nothing. A real <button> with aria-expanded controls it.
  • Layers in each panel:
    1. What it means: the reviewed glossary text, with the reviewer and the date.
    2. In your design: sentences computed from the R output of this design. Example: "The 21 2FIs fall into 7 groups of 3. Example: Temp:Pressure = Speed:Feed = Time:Depth."
    3. Watch this part: a link to the matching chapter of the introduction video.
    4. Phase 2, charts only: "Explain this chart with AI", off by default (Section 9.5.1).
  • Show explanations: a switch on the step rail opens all panels at once. The device remembers the switch.
  • Sources: content/glossary.json (fields key, term, text, reference, reviewed_by, reviewed_on) and lib/report/explain.ts (fixed sentence templates). No LLM writes help text. scripts/build-glossary.mjs builds the MathML into data/glossary.json (decision P16). An entry without a reviewer shows "Draft, not yet reviewed" (decision P3). Until the video exists, a panel has layers 1 and 2 and a link to the glossary entry (decision P13).
  • Review status (2026-10-19). Alan R. Vazquez reviewed 33 of the 35 entries. These 33 entries have reviewed_by and reviewed_on (decision F8). The texts of generators, clear_2fis and effect_heredity use his words. The entries all_2fis_clear and guarantee have new texts (decision F9). They show "Draft, not yet reviewed" until he answers again (Section 14.4). The references now include Mee (2009), Ryan and Bulutoglu (2010) and Xu (2009) (decision F10).

9.5.1 AI chart explanation (Phase 2, opt-in)

  • The feature is off by default.
  • The first use opens a dialog in the page. It shows the exact data to be sent (the numbers behind the chart and the factor names) and the provider.
  • The explanation is labeled as AI-generated.
  • Each number in the explanation must occur in the data that was sent. Otherwise the tool does not show the explanation.

9.6 Factor order (isomorphism, Phase 1)

  • The card shows the factor order. The user changes it with "Move up" and "Move down" buttons.
  • The page announces each move. Example: "Temp moved to position 2 of 7."
  • A ? panel explains: the order does not change the WLP, the resolution or the number of clear 2FIs. The order changes which named effects are aliased and which named factors have all 2FIs clear. Example: in the FrF2 design for 9 factors in 32 runs, only position 9 has all 2FIs clear.
  • The design properties show the alias chains with the real factor names, so the user can see the effect of the order.

9.7 Wording

  • Labels use plain academic wording: "Maintained by", "Privacy", "Citation", "R code", "All files (.zip)", "Report contents".
  • No marketing language, no second-person slogans, no exclamation marks.
  • Messages state facts. Error messages say what failed and what the user can change.

9.8 Branding

  • Name: EXPERTA, with the subtitle "Fractional Factorial Design Translator" (R18). Constants APP_NAME, APP_SUBTITLE and APP_FULL_NAME in lib/site.ts. The browser title and the citation use the full name "EXPERTA: Fractional Factorial Design Translator".
  • Interface tokens: accent #625d96 and accent dark #4c4977 (R19: the Dark2 purple #7570B3, darkened, because #7570B3 has only 4.44:1 on white); from ChatISA: light tan #edece2, medium tan #ccc9b8, dark tan #70685c, ink #000000, warm white #faf9f7. The accent has 5.96:1 on white, 5.66:1 on warm white and 5.02:1 on light tan; a unit test checks the WCAG AA values (brand-colours.test.ts).
  • Fonts: Source Serif 4 (display) and Arial (body). Self-hosted. No font CDN in the app.
  • Chart palette (ColorBrewer Dark2, measured, R19): series purple #7570B3, orange #D95F02, teal #1B9E77, gray #666666, in this order, at most four colours. Dark2 green (2.98:1) and mustard (2.06:1) fail the 3:1 contrast that chart marks need on white. In ColorBrewer's order, teal and magenta are almost the same colour for colour-blind readers (OKLab distance 1.7), and so are orange and brown (1.8). The smallest OKLab distance of the chosen order, for normal vision and simulated protanopia, deuteranopia and tritanopia, is 21.4 for 2 series, 10.7 for 3 and 7.2 for 4 (replication_materials/findings/palette-check.mjs). From 3 series up, direct labels or distinct shapes are required; above 4 series, shapes and labels carry the difference. Black is for text and axes only. FrF2's own plot functions get the palette through their colour arguments.
  • Logos: both logos side by side with equal weight, each in its own colours on a white header.
    • Tecnológico de Monterrey: public/brand/tecnologico-de-monterrey-blue.svg (PNG fallback in the same folder).
    • Miami University: the horizontal lockup from ChatISA (assets/logo-horizontal-stacked.png).
  • Favicon: an SVG cube with four of its eight corners filled in the accent: the 23−12^{3-1} half fraction.
  • Phase 1 has a light theme only. The colours are tokens, so a dark theme can come later.

9.9 Mathematical notation

Lessons from hf_arxiv_control_charts (R Shiny with MathJax):

  • Text that the app computes (27−32^{7-3}, I=ABCE=⋯I = ABCE = \cdots, resolution IV, A4=7A_4 = 7) is built as HTML elements (<sup>, <sub>). It is not parsed as LaTeX.
  • The glossary math is converted to MathML at build time (KaTeX with output: "mathml", pinned). Chrome draws MathML natively, so the app loads no math fonts and no math style sheet, and screen readers read the formulas. This specification page uses the same method (pandoc with MathML output).
  • Any LLM text (Phase 2 explanations) uses only \(...\) and \[...\]. The prompt forbids $ as a delimiter. A normalizer runs before rendering: it converts stray $ delimiters, protects currency, repairs JSON escapes that remove a backslash (for example \b in \beta), and removes unmatched delimiters.
  • Sanitizing happens before KaTeX, not after it. KaTeX runs with trust: false.
  • Display math scrolls horizontally inside its own box.
  • A render test checks that the output contains no .katex-error element.

9.10 Accessibility

  • Target: WCAG 2.1 AA. Also meet the WCAG 2.2 additions for target size and focus not obscured.
  • Skip link. One global announcer (ChatISA pattern): the markup of the app has one polite and one assertive live region (components/a11y/Announcer.tsx). The route announcer of Next.js, in a shadow root, reads only the page title after a navigation.
  • Focus moves to the step heading after each step change.
  • Each step sets the page title "Step {n}: {title} | EXPERTA". The workspace keeps this title with an observer of the document head, because Next.js puts its metadata title back after each render (decision C13).
  • Required fields (factor name, low level and high level) have aria-required="true", and their "*" marker is aria-hidden (decision C13).
  • The accessibility sweep is a guard in npm run check on every page. It runs the five custom checks of Section 11 as Playwright assertions (decision C13).
  • A select of step 2 whose value is not in its list shows that value as "{value} (not available)". The error of the field stays, and "Generate design" stays unavailable (decision C16).
  • Focus rules (decision C14). No focus drops to the page body (WCAG 2.4.3).
    • "Delete all" moves focus to "New design". "Keep projects" returns it to "Clear".
    • "Delete record" moves focus to the "Your projects" heading. "Keep record" returns it to the "Delete" of that record.
    • After a failed "Delete project", focus returns to the "Project actions: {name}" button of that project. After a failed "Delete all", focus returns to "Clear". The store error is shown and announced.
    • Cancel of a translation returns focus to the request field, or to the Answer field.
    • A clarification question moves focus to the Answer field. This applies to the first one, which makes the project, and to each later one. A refusal of the first request moves focus to the request field.
    • The footer Retry and the footer Cancel of an R run move focus to the step heading.
    • "Previous rows" and "Next rows" use aria-disabled at the ends. "Interpret request" and "Send answer" use aria-disabled while busy.
  • Status is always text. Colour is never the only signal.
  • Required fields have a visible marker and a note that explains the marker.
  • The run sheet is a real <table> with a caption and scope headers. Large tables use pagination, not virtual scrolling.
  • Single column at high zoom.
  • Reduced motion is respected.
  • Phase 2 plots get text alternatives and a data table.
  • The introduction video has captions and a transcript (Section 10).

10Introduction video

10.1 Content

  • One video of about 2 minutes 15 seconds for each minor or major release.
  • Chapters follow the steps: introduction, 1 Describe, 2 Confirm, 3 Design, 6 Report and files, closing card. Phase 2 adds chapters for steps 4 and 5.
  • The narration uses plain academic wording. The draft script has nine beats (mockup 06).
  • A Spanish version (narration and captions) ships with version 1.0. A Spanish speaker reviews the translation.

10.2 Production

  • Tool: the narrated-demo-video skill (Playwright footage, narrated beats, title cards, ffmpeg assembly).
  • Narration: ElevenLabs v4. The word timings from the timestamp endpoint set the captions.
  • Music: quiet CC-BY music under the narration, lowered while the narrator speaks, and credited on the closing card.
  • Footage: Playwright films the real app. The translation step uses the recorded responses of the end-to-end tests, so filming makes no live API call. FrF2 runs in WebR.
  • Output: self-hosted MP4 (1920 x 1080, 30 fps) with WebVTT captions in both languages and a transcript page. No third-party video player.
  • Chapter times come from the measured beat lengths. The ? panels link to them ("Watch this part").

10.3 Title cards

  • Warm-white field #faf9f7, an accent rule (#625d96, R19) at the top, both logos in their own colours with equal weight, and black titles.
  • Measured contrast for normal vision and for simulated protanopia, deuteranopia, tritanopia and achromatopsia (version 2, with the Miami Red rule): black titles 19.9:1 or more, Tec blue 8.3:1 or more, Miami Red 4.8:1 or more (card_contrast.py). The accent rule is measured again before the video release (Section 17.1).

10.4 Keeping the video current

  • A stale check compares screenshots of the filmed screens with the current app.
  • A change flags the video for the next minor or major release. Patch releases do not need a new video.
  • The landing page shows the version that the video records.

11Software tests

All tests are in replication_materials/tests/.

In this document, "CI" means the local check command (npm run check). When the project has a remote repository, GitHub Actions runs the same command.

Layer Tool What it proves
Unit vitest zod rules; evidence check; candidate-number finder; agreement rule; pre-checks; codegen snapshots; displayed code = executed code; each ? key has a glossary entry, and the built glossary equals its source (each entry has a reviewer: release gate with FFD_RELEASE=1, decision P3); the fixed scope templates contain no advice words ("try", "instead", "recommend", "consider", "should"); architecture.json paths exist; each cell of the "By stage" process view matches its events.
R unit testthat (native R 4.6.1) Computed WLP = DoE.base::GWLP() = stored catalogue WLP for each catalogue entry within the supported limits. The comparison with the stored WLP uses the stored values that are not NA, accepts the verified errata and leaves out the refused entries. Resolution and guarantee class are correct. FrF2 selects the .1 entry when one exists. Each pre-check rule reproduces the FrF2 behaviour it prevents. Mutation tests: change one cell or remove one run, and the post-check must fail.
Namespace Rscript and WebR Every R snippet runs in a fresh session with only base packages attached, with no error and no warning (Section 7.2).
Differential Node + WebR, and Rscript For the full Phase 1 grid plus random specs and seeds, the WebR output (design matrix and report JSON) is byte-identical to the native R output. This includes the run order for date seeds. A subset also runs in Chromium.
Exports vitest + WebR Each file is the same from each place where it is offered. Round trip: export, edit responses, upload, and the factor-column check. Import of a project file rebuilds the same SHA-256.
Performance Node + WebR, Playwright Cold and warm times per task. Latency of each translation provider. Sets the time budgets, the translation deadline and the supported limits. CI fails if a supported task is over its budget. Results go to CSV in replication_materials/tests/perf/.
End-to-end Playwright (Chromium) The full flow, including a returning visit to the last page. The translate API is replaced by recorded fixtures. CI makes no LLM calls.
Accessibility Playwright + axe WCAG 2.1 AA sweep plus the ChatISA custom checks (empty tab stops, labels on generic elements, placeholder contrast, required markers, page titles). A manual NVDA and JAWS check before each release.
Rendering Playwright No .katex-error element in the glossary and in Phase 2 explanations.
Video Playwright Stale check of the filmed screens (Section 10.4).
Live smoke Manual or nightly A small set of real calls to each provider to find model changes.

12Paper evaluation

The benchmark and the results are in replication_materials/evaluation/.

12.1 Benchmark slices (Phase 1)

Slice Content
S1 The 36 tasks of Vazquez et al. (2026), in their plain wording: 8 runs with 4-7 factors, 16 runs with 5-15 factors, 32 runs with 6-26 factors.
S2 Wording variants of S1: runs first or factors first, number words or digits, practitioner stories, Spanish.
S3 Requests that give a resolution need, for example "9 factors, main effects clear of 2FIs, fewest runs".
S4 Named factors with levels and units.
S5 Replications, center points, seeds.
S6 Requests that need clarification.
S7 Out of scope, with boundary pairs ("check curvature" and "model curvature").
S8 Not supported in this version (blocking, split-plot, estimable 2FIs, Plackett-Burman, user generators, foldover).
S9 In scope but not feasible, for example 8 factors in 8 runs.
  • About 300 prompts. Each prompt runs 10 times.
  • Gold specs are written by the team and reviewed by Alan R. Vazquez. Gold designs come from native R.
  • Claude drafts the S2 paraphrase candidates. A person reviews each candidate. Claude does not set gold labels.

12.2 Metrics

  1. Outcome accuracy (4×44 \times 4 confusion matrix).
  2. Field-level exact match.
  3. Design equivalence: the catalogue entry and the WLP match the gold design. The factor order counts only when the prompt sets it.
  4. Silent error rate: the fraction of requests with a wrong spec and no flag on the card. This is the main safety metric.
  5. Flag performance: the fraction of wrong fields that the evidence check or the agreement flags mark, and the false alarm rate.
  6. Unanimous error rate: how often a spec on which all voters agree is wrong.
  7. Optimality rate on S1, next to the direct-generation results of Vazquez et al. (2026).
  8. Consistency across the 10 repetitions. Latency (median and p95). Cost per request.

12.3 Arms (ablations)

Arm Content
A1 to A3 Each LLM alone: gpt-6.1-sol, claude-opus-5-5, gemini-4-argon.
A4 The three LLMs with agreement flags.
A5 The three LLMs and Jev with agreement flags.
A6 Jev alone, for the outcome and the number selection only.
A7 A small number of prompt part orders, on the best single model.

12.4 Rule for the production default

  • Before the test-set run, the authors write a rule, for example: "Use the ensemble if it reduces the silent error rate by at least X% with a p95 latency of at most Y seconds and a cost of at most Z per request."
  • The rule, with X, Y and Z, is committed to replication_materials/evaluation/ before the run.
  • The test-set results then select the mode. The paper reports the rule and the result.

12.5 Validity

  • Development and test split. Prompt work uses the development set only. The test set is frozen. It runs once for each final prompt version.
  • Few-shot examples never come from the test set.
  • Raw outputs are saved as JSONL, with the model id that each provider returned. Scoring is a separate, deterministic step. Anyone can make all tables and figures again without new API calls.
  • Jev is not deterministic. The 10 repetitions report its variation with the other arms.
  • The harness uses the same translator module as the app.

13Operations, privacy and security

13.1 Operations

Item Value
Process Vercel functions (Fluid compute, Node.js 22). No database other than the Redis counters. The counters of the rate limit and the spend caps are in Upstash Redis. Local runs keep them in memory. Each Redis call has a time limit of 1 s, retries included (config/store-budgets.json). A call over the limit is a store failure.
Rate limit Per address on /api/translate. Defaults 10 per minute, 100 per day. Set in config. The key is the HMAC-SHA256 of the address with RATE_LIMIT_SALT, in hex. The store keeps no address. A refused request does not count. The minute key lives 120 s and the day key lives 172,800 s.
Spend caps A daily cap in USD for each provider, from token usage and config/pricing.json. A provider at its cap is left out. When no LLM provider is left: "Interpretation is paused until tomorrow. You can fill in the form yourself." The default is USD 5 per provider per day; the values depend on the selected mode (Section 12.4). An LLM call that the deadline cuts off is charged at an upper bound. The input tokens are the UTF-8 bytes of its input (instructions, messages and schema). The output tokens are the full output budget. The cost is in integer micro-dollars. Before the calls, one atomic step reserves the worst-case cost if the spent amount plus the reserve is at most the cap. After the calls, a second step settles the real cost against the reserve. A settle that fails does not change the reply. A cost that is not finite or is negative blocks the voter until the next UTC day. A store that is missing or fails gives "Interpretation is not available now. You can fill in the form yourself." (decisions A10, AP2 and AP3).
Input limits 4,000 characters per turn. 3 clarification rounds.
Logs Time, outcome, mode, tokens, latency, cost, model ids, and the versions of the prompt, the schema and the Jev questions. No request text and no IP address.
Headers The page policy applies to all routes: default-src 'self'; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval'; worker-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'. The worker policy applies to /workers/* and /runtimes/*. It is the page policy with 'unsafe-eval' added to script-src. WebR's Emscripten R.js and webr-worker.js call eval in the worker, and a worker takes its policy from its own script response (measured on 2026-10-17). Pages have no eval. All routes also send COOP same-origin, COEP require-corp and Referrer-Policy no-referrer. During the alpha (RELEASE_STAGE is alpha), they send X-Robots-Tag noindex.
Secrets Only in .env. .env is in .gitignore.
Prompt injection The output is schema-locked. R code comes only from templates. The user confirms the spec. The worst result is a wrong spec that the user sees before R runs.
Deployment Vercel Git integration: main goes to production at expertadoe.app, and other branches go to previews. The production deployment also answers at experta-doe.vercel.app, and www.expertadoe.app redirects to expertadoe.app (308). Browser storage is per address, so the projects of one address do not show at the other. The paper and other public links name only expertadoe.app. The domain sends no mail, and its SPF and DMARC records reject mail that claims it. Self-hosting (a Dockerfile and the ChatISA start script) waits for the public release (decision A4).

13.2 Configuration (.env)

Variable Use
OPENAI_API_KEY, OPENAI_MODEL OpenAI voter (gpt-6.1-sol).
ANTHROPIC_API_KEY, ANTHROPIC_MODEL Anthropic voter (claude-opus-5-5).
GEMINI_API_KEY, GEMINI_MODEL Google voter (gemini-4-argon). The code passes this key explicitly, because the SDK default name is GOOGLE_GENERATIVE_AI_API_KEY.
JEV_API_KEY, JEV_MODEL TypeSafe voter (jev-1.13.0). The code passes this key explicitly, because the SDK default name is TYPESAFE_API_KEY.
TRANSLATE_MODE single or ensemble.
TRANSLATE_SINGLE_PROVIDER The provider for single mode.
TRANSLATE_DEADLINE_MS Deadline of the parallel step, from the performance tests.
RATE_LIMIT_PER_MIN, RATE_LIMIT_PER_DAY Rate limit.
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN Redis store for the counters. The code uses these names first.
KV_REST_API_URL, KV_REST_API_TOKEN The other name set that the Vercel integration can make. The code uses it when the first set is absent.
RATE_LIMIT_SALT Secret for the rate-limit keys. At least 32 characters. Redis variables without such a salt give no store.
REVIEW_KEY Key of the review page (Section 14.4). At least 24 characters.
GITHUB_REVIEW_TOKEN, GITHUB_REVIEW_REPO Token (Issues read and write, one repository) and repository (owner/name) for the review answers.
DAILY_SPEND_CAP_USD_OPENAI, ..._ANTHROPIC, ..._GEMINI, ..._JEV Spend caps.
MAX_REQUEST_CHARS Input limit.
NEXT_PUBLIC_R_SOFT_TIMEOUT_MS, NEXT_PUBLIC_R_HARD_TIMEOUT_MS R time budgets from the performance tests.
NEXT_PUBLIC_R_STALL_MS Time without progress before "Retry" appears during the engine start, from the performance tests.
NEXT_PUBLIC_FFD_TEST_HOOKS Set to 1 only by the browser-test build. It gives the tests access to the R engine. A production build on Vercel fails if it is set.
FFD_LIVE, FFD_LIVE_VOTERS Tests only: run the live tests, with the listed voters. Each live run needs the approval of the authors.
FFD_BASE_URL Tests of the deployed site only: the address of the site. Required.
FFD_SLOW_RUNS Tests of the deployed site only: the number of trials of the slow-device start.
FFD_LIVE_LIMITS Tests of the deployed site only: set to 1 to check the shared rate limit. The check stops if provider keys are set.
FFD_EXPECT_CSP Tests of the deployed site only: set to 1 to check the exact policy headers.
ELEVENLABS_API_KEY Video narration only. Not used by the app.

13.3 Privacy notice

  • Single mode: "Your request text is sent to {provider} to interpret it. Do not include confidential data. The design is made in your browser."
  • Ensemble mode: "Your request text is sent to OpenAI, Anthropic, Google and TypeSafe to interpret it and to check the result. Do not include confidential data. The design is made in your browser."
  • Phase 2 opt-in: the dialog of Section 9.5.1.
  • The landing page has a "Privacy" block with the same text and a link to the details.
  • The server keeps no request text and has no accounts. The log has no request text and no IP address.
  • The rate limit counts the requests of each network address for one minute and for one day (UTC). The Redis database (Upstash) holds a keyed hash of the address (HMAC-SHA256 with RATE_LIMIT_SALT), not the address, for at most two days.
  • The host, Vercel, keeps its standard request logs, which include the IP address.
  • The review page (Section 14.4) sends the name and the comment of an author to a GitHub repository as an issue. The server does not log the key, the name or the comment.

14Documentation

14.1 Style

  • About 80% ASD-STE100.
  • Procedures: at most 20 words per sentence. Descriptions: at most 25 words per sentence.
  • Active voice. One instruction in each sentence.
  • Technical names (resolution, aberration, alias, generator) are allowed.
  • Plain academic wording (Section 9.7).
  • scripts/ste-check.mjs reports the percentage of sentences that meet these rules. CI fails below 80%.

14.2 Documents

File Content
README.md What the tool does, how to run it, how to test it.
docs/user-guide.md How to use the tool.
docs/decisions/ADR-NNN-*.md One architecture decision record for each decision in Section 2.4.
content/glossary.json Help text. Reviewed by Alan R. Vazquez.
docs/architecture/architecture.json Source of the interactive architecture page.
replication_materials/plans/ This specification, the decision log and the implementation plans. The web version of this specification is built from the Markdown file by scripts/build-spec-page.mjs (pandoc).

14.3 Interactive architecture page

  • The app page /architecture renders docs/architecture/architecture.json.
  • The JSON lists components, data flows, source file paths, tests and decision records.
  • The page shows clickable diagrams. A click on a component shows its purpose, inputs, outputs, files, tests and decision records.
  • Drift test: a unit test fails if a path in the JSON does not exist, or if a source module is not in the JSON.
  • Each phase updates the JSON.

14.4 Review questions page (alpha)

The page /review collects the answers of the authors during the alpha. Decisions A12 to A14 and AP6 apply.

  • No other page links to /review. The link has the key in its fragment: /review#key=.... The page keeps the key in sessionStorage (ffd:review-key) and removes it from the address bar. It sends the key in the header x-review-key.
  • The page asks 55 questions as data: the 13 guarantee regions, the class sentences, center points, replications and resolution-only entries. It also asks about entries without an MA claim, the refused defaults 26-17.1 and 27-18.1, the 35 glossary entries, R23, the references and "Other comments". The progress count has the 54 questions that have choices.
  • The choices are Agree, Change and Not sure. Change needs a comment. "Other comments" has no choices and needs a comment. A comment has at most 4,000 characters and a name has at most 100 characters. The name is kept in localStorage (ffd:review-name).
  • Four questions are asked again after the answers of 2026-10-19 (decision F6): the claim for 128 runs with 25 to 39 factors (guarantee.region.128.25-64), the entries without an MA claim (guarantee.no-claim, title "Claims for the other catalogue entries"), and the glossary entries glossary.all_2fis_clear and glossary.guarantee. The file data/review-asked-again.json lists them and names the last issue number before the change (after: 65). An answer in an issue up to that number shows under the question as an earlier answer and does not count. Only an answer in a later issue counts. The rule holds on the page, in the read-back and in the CSV export. "Other comments" keeps every answer. The question about the refused defaults is not asked again (decision F7).
  • Each answer is one GitHub issue. The title is [alpha-review] {question id}: {choice label}. The labels are alpha-review and one topic (guarantee, glossary, r23, references or other). The first line of the body is a marker with the question id and the choice.
  • GET /api/review reads the answers and needs the key. POST /api/review files one issue. The limits are 30 per minute and 300 per day for each address (prefix rv), counted for both methods together and before the key check. The body has at most 25 KB, because a comment of 4,000 control characters and a name of 100 take 6 bytes each in JSON. The server compares the key in constant time. REVIEW_KEY has at least 24 characters.
  • The read-back counts only the issues that the token owner made with the label alpha-review and without the label withdrawn. The newest answer to a question wins. A closed issue still counts. The server caches the list for 60 seconds in each instance.
  • The messages are fixed strings in lib/review/answer.ts, for example "The review key is not valid." and "The review service is not available now."
  • node scripts/export-review.mjs writes the answers to one CSV file, one row for each issue with a marker. It reads the issues with the GitHub CLI of the author. The column counted uses the rule of the read-back. The default file is alan_feedback/alpha-review-answers.csv, which git ignores. The authors decide if the answers go into the public replication materials.

15Replication materials

replication_materials/
  conversations/  Claude Code session JSONL files and subagent transcripts.
                  A secret scan runs before the copy.
  plans/          This specification (Markdown and web page), its figures,
                  the decision log and the implementation plans.
  mockups/        The interface mockups: standalone HTML, source fragments,
                  PNGs, the selected options, and the R and Python checks.
  process/        process.json: the event log behind the process figure.
  skills/         A copy of each skill used, with its LICENSE, and a README
                  with the source URL, version, commit and SHA-256 of each.
  tests/          All test suites (Section 11) and performance CSVs.
  evaluation/     Benchmark, the pre-registered rule, raw LLM outputs (JSONL),
                  scores, figures.
  memory/         A copy of the Claude Code project memory files.
  environment/    Claude model and effort, Claude Code version, enabled plugins
                  and the output style, Node and npm versions, R sessionInfo(),
                  WebR version, pandoc version, package-lock.json, OS.
  sync.ps1        Copies the transcripts, the memory, the skills and the
                  versions, and fills the counts in process.json.
                  Run it at the end of each session or phase.

Known values on 2026-10-15:

Item Value
Claude model Claude Opus 5.5 (claude-opus-5-5)
Effort level xhigh
Claude Code 2.1.299 for version 1 of this spec; 2.1.300 for version 2
Skills used superpowers 6.4.1 (brainstorming, with its visual companion); typesafe 0.5.7 (read from the marketplace copy); narrated-demo-video (planned for the video); artifact-design (web page)
Output style explanatory-output-style plugin
Node / npm 22.14.0 / 11.5.2
Native R 4.6.1 with FrF2 2.3.5, DoE.base 1.2.5, igraph 2.3.3, sfsmisc 1.1.26, scatterplot3d 0.3.45, conf.design 2.0.0
WebR 0.6.0 (R 4.6.0)
npm packages next 16.3.8, react 19.3.0, zod 4.6.5, tailwindcss 4.3.3, typescript 5.9.3, vitest 4.1.11, @playwright/test 1.63.0, fake-indexeddb 6.2.5, webr 0.6.0 (exact pins in package.json)
WebR packages 29 packages, pinned by SHA-256 in data/runtime-manifest.json
pandoc 3.12
Python 3.14.8
git 2.49.0
OS Windows 11 Enterprise 10.0.26300

16Proposed repository layout

fractional_factorial/
  app/                     Next.js pages: / (landing), /app (workspace),
                           /glossary, /architecture
    api/translate/route.ts
    api/explain-chart/route.ts   (Phase 2)
    review/page.tsx        review questions page (alpha, Section 14.4)
    api/review/route.ts
  components/              shell/, steps/, spec-card/, design/, help/, a11y/, code/
  lib/
    translate/             schema.ts, prompt.ts, voters.ts, agreement.ts,
                           candidates.ts, evidence.ts, translate.ts
    spec/                  validate.ts, precheck.ts, defaults.ts, seed.ts
    codegen/               frf2.ts
    webr/                  client.ts (worker manager)
    report/                types.ts, guarantee.ts, explain.ts
    projects/              store.ts (IndexedDB), pointer.ts, schema.ts
    exports/               xlsx.ts, csv.ts, report-html.ts, zip.ts, import.ts
    ops/                   ratelimit.ts, spend.ts, log.ts, kv.ts, stores.ts,
                           scripts.ts
    review/                questions, answer, key, GitHub client, handler
    security-headers.ts    page and worker Content Security Policy
  r/ffd_report.R           report helper (one source file)
  public/
    workers/webr-worker.mjs
    r/                     build copy of ffd_report.R
    runtimes/              WebR and package mirror (generated, not in git)
    brand/                 logos, favicon.svg
    video/                 MP4, WebVTT captions (English, Spanish)
  content/                 glossary.json, messages.json
  data/                    catalogue-summary.json, guarantee-table.json (generated)
  prompts/                 versioned translation prompts
  scripts/                 setup-runtimes.mjs, build-catalogue.R, ste-check.mjs,
                           build-spec-page.mjs
  video/                   capture, narration, cards and timeline scripts
  docs/                    user-guide.md, decisions/, architecture/
  refs/                    papers and FrF2 documentation (not committed)
  replication_materials/   see Section 15; tests/deployed/ holds the checks of the
                           deployed site

17Open items and risks

17.1 Open items

Item Owner Needed by
Review of the guarantee table (Section 7.7). Done on 2026-10-19 for 12 of the 13 regions, the class sentences and the additions (center points, replications, resolution only). Asked again (Section 14.4): the claim for 128 runs with 25 to 39 factors, and the claims for the other catalogue entries. The refused defaults 26-17.1 and 27-18.1 stay refused until Alan R. Vazquez revises the FrF2 findings. Alan R. Vazquez Public release. The claims of Section 7.7 apply now: in the 12 regions that Alan R. Vazquez confirmed, for 40 to 64 factors in 128 runs (his answer #61), and for 25 to 39 factors in 128 runs by decision F2 (Xu, 2009, and the check at generation time) until he answers.
Review of the glossary (Section 9.5). Done on 2026-10-19 for 33 of the 35 entries drafted in Milestone 3B. The entries all_2fis_clear and guarantee have new texts, show "Draft, not yet reviewed" and are asked again (Section 14.4). Alan R. Vazquez Public release (release gate, decision P3)
Review of the gold labels (Section 12.1). Alan R. Vazquez Milestone 4
The rule for the production default, with X, Y and Z (Section 12.4). Both authors Before the test-set run (Milestone 4)
Phase 2 upload reads .xlsx files that Excel saves (shared strings, styles); the 3C writer uses inline strings only. Fadel M. Megahed Phase 2
The stall limit (4 s) of the engine start was measured on one fast desktop computer. Fadel M. Megahed Done on 2026-10-19: the limit is 16 s. It comes from 20 trials with the Lighthouse mobile profile (150 ms latency, 1,638.4 kbit/s). The trials ran in a Docker container. Its CPU quota makes the R worker 4 times slower. The longest gap between progress changes was 5,101 ms; the engine was ready after about 165 s. The limit is 3 x the longest gap, rounded up. The data are in replication_materials/tests/perf/slow-start-cpu030.csv; the method is in slow-cpu-docker.md. The alpha trials (5 s limit) slowed the page only, because CDP cannot slow a worker.
Measure the stall limit on a real low-end phone. Fadel M. Megahed Done on 2026-10-19 with a Docker CPU quota calibrated to 4 times slower; a real phone remains a check for later.
Rate limit and spend cap values. Fadel M. Megahed Done in the alpha release: the defaults, 10 per minute, 100 per day and USD 5 per provider per day (decision A9).
Supported limits for runs and factors. Measured Done in Milestone 2: data/supported-limits.json. The ceiling is 120 seconds (plan decision P8, 2026-10-15).
Review of the Spanish narration. A Spanish speaker Video release with version 1.0
A check of the name EXPERTA for conflicts with other software and organizations. Both authors Public release
Send the FrF2 findings to the FrF2 maintainer (draft in replication_materials/findings/) Both authors When the authors decide
The Content Security Policy header (Section 13.1). WebR needs wasm-unsafe-eval and worker sources, so the policy is set and tested with the deployment. Fadel M. Megahed Done in the alpha release: the page policy and the worker policy of Section 13.1, measured on 2026-10-17 (decision A11).
Download progress for WebR's own files during the engine start. Fadel M. Megahed Done in Milestone 3C: the footer says "R engine: starting R" until the first package message, and the stall timer stops after the last package byte. R.wasm sends no progress, and a second request for it transfers the full 12.3 MB again, so a prefetch would double the largest download (decision C3, measured).
A save of the R library that fails after IndexedDB opens (for example a full quota) leaves the engine start without an answer from WebR 0.6.0. The user sees "loading has stopped" and Retry. Fadel M. Megahed Cross-browser tests (Milestone 4)
Jev's outcome criteria misjudge some design requests, for example requests with level ranges (Section 3.3). Review the wording before Jev's outcome counts again. Fadel M. Megahed, Alan R. Vazquez Milestone 4
The spend caps can be overshot by parallel requests: the cap is checked before a call and the cost is recorded after it (up to the deadline later). Reserve the worst-case cost before the call, or limit the translations in flight, before deployment. Fadel M. Megahed Done in the alpha release: the reservation of Section 13.1 (decisions A10, AP2 and AP3).
The rate limit keys on the first x-forwarded-for entry, which a client can forge behind a proxy that appends to the header (decision P11). Before deployment, take the address from a header that the chosen host overwrites, or from the right-most entry after a configured number of trusted proxy hops (TRUSTED_PROXY_HOPS). Fadel M. Megahed Done in the alpha release: Vercel overwrites x-forwarded-for (Vercel documentation, read on 2026-10-17), so clientIp() stays.
Confirm the clear-2FI definition for full factorials (R23). The question is on the review page (Section 14.4). The Dark2 purple of R19 is settled (decision of Fadel M. Megahed, 2026-10-17). Alan R. Vazquez Done on 2026-10-19: he agreed to the R23 text.
Confirm the references of Section 1.8 (decision P4) and review the glossary entries for effect hierarchy, effect sparsity, effect heredity and clear 2FI. Alan R. Vazquez Done on 2026-10-19: he confirmed the references and reviewed the entries. He asked to add Mee (2009), Ryan and Bulutoglu (2010) and Xu (2009) (Section 19).
Measure the main-thread parse of the largest reports (up to 32,768 rows) in the real flow (Milestone 2 review). Fadel M. Megahed Done in Milestone 3C: 40 ms in Chromium for 32,768 rows (3.9 MB), under the 50 ms long-task line (decision C4, measured).
The focus after "Clear" and after Cancel, and the size of the Home link (Milestone 2 review). Fadel M. Megahed Done in Milestone 3C: the focus rules of Section 9.10, and the axe rule target-size passes (decision C14, measured).
Each save reads and parses all stored projects again (about 0.4 s of main thread per card edit with the largest stored report, measured in Node by the final review of Milestone 3B). Store from the saved project and measure in the browser. Fadel M. Megahed Done in Milestone 3C: each save replaces the saved project in the list and does not read all projects again. Measured with the largest report: store.list() 73 ms and store.put() 111 ms per save (decision C5).
The privacy notice is fixed at build time: the landing, workspace and privacy pages are static. Rebuild after a change of TRANSLATE_MODE or TRANSLATE_SINGLE_PROVIDER, or render these pages dynamically. Fadel M. Megahed Done in the alpha release: the pages stay static, and a change of mode needs a new deployment.
Measure the video title cards again with the accent rule (Section 10.3). Fadel M. Megahed Video release (Milestone 4)
Self-hosting: a Dockerfile and the ChatISA start script. Self-hosted runs keep the counters in memory; Vercel uses Redis or refuses the request. Both authors Public release (decision A4)
Set a time limit for the Redis calls (KvClient) from the Upstash latency measured at Checkpoint B. Fadel M. Megahed Done after the alpha release (2026-10-18): 100 pairs of requests to the deployed route, one with a Redis call and one without, gave a median of 17 ms and a largest call of 59 ms. The limit is 1 s by the rule 10 x the largest call, rounded up to a whole second (scripts/derive-store-budget.mjs). The limit includes the retries of the Upstash client. The data are in replication_materials/tests/perf/alpha-upstash-latency.csv.
scripts/ste-check.mjs, named in Section 14.1, does not exist in the repository. Fadel M. Megahed Public release
Measure the main-thread parse of the largest report again under the Content Security Policy. The 40 ms of Milestone 3C was measured with the Zod JIT, which the policy now blocks. Fadel M. Megahed Public release
The routing rule of Phase 4: a reviewed decision table (recommended, Section 1.9) or the LLM's own judgment. Both authors Before a Phase 4 plan
The decision table of Phase 4 and the gold families. Alan R. Vazquez Before a Phase 4 plan
The scope of the paper: Phase 1 alone, with Phase 4 as future work, or a second paper. Both authors Done on 2026-10-19 (decision F14, Fadel M. Megahed): the paper covers the tool up to and including the design families of DoE.wrapper (Phase 4) and their benchmarks. The aim is that a practitioner writes a short text with the factors and the constraints, and EXPERTA leads from the choice of a design, or of a sequence of designs in sequential experimentation, to the analysis. The order of the work after the review fixes is planned again in a separate design.
The field of application. Alan R. Vazquez proposes to tailor EXPERTA to one field (for example biotechnology, the food industry or manufacturing), because the readers of JQT and Quality Engineering already know FrF2 (his comment of 2026-10-19, decision F13). He will search for papers on applications to choose the field. His answers stay out of the public repository (Section 14.4). Both authors Before the Milestone 4 test set and the paper draft

17.2 Risks

Risk Mitigation
First visit downloads about 50 MB. Slow networks wait a long time. Prewarm on page open. Progress bar. IndexedDB cache. The user can fill the card while R loads.
An LLM model changes or is retired. gpt-6.1-sol has no dated snapshot. Log the returned model ids. Live smoke tests. The evaluation records the ids.
Jev is in early access and not deterministic. Pinned version. Ten repetitions in the evaluation. Jev only adds flags; it never sets a value without the LLMs or the user.
The ensemble sends the request to four providers. The notice names them. Single mode is available. The evaluation decides whether the ensemble is worth it.
The MA claim is wrong for some catalogue entries. The MA statement applies only in the regions that Alan R. Vazquez confirmed, and for 128 runs with 25 to 39 factors by decision F2 with the check at generation time (Section 7.7). WLP checks against the catalogue and, for 128 runs with 25 to 40 factors, against Xu's design. The .1 selection test.
An R function needs the search path. The namespace test (Section 7.2).
A user gets around the per-IP rate limit. The daily spend caps limit cost. Under parallel requests a cap can be exceeded by the cost of the requests in flight (Section 17.1). The manual path still works.
Very large run sheets are hard to use with a screen reader. Pagination. Table caption with the size. CSV and Excel export.
WebR or a package binary changes. Pinned versions. Self-hosted mirror with SHA-256 manifest. Import keeps the stored run sheet.
The video becomes out of date. Stale check (Section 10.4).

18Phase 1 implementation sequence

The implementation plan for Phase 1 has four milestones. Each milestone ends with passing tests.

  1. R core. ffd_report.R (generators without the search path), build-catalogue.R, catalogue summary, guarantee table (conservative until the review; see Section 7.7 for the claims after it), seed rules, native R tests, namespace test.
  2. Browser engine and projects. Next.js shell (landing page, workspace, step rail), runtime setup, WebR worker, codegen, project storage (IndexedDB and the pointer), differential tests, performance tests.
  3. Translation, interface and exports. Schema, prompt, evidence check, voters and agreement flags, translate route, operations controls, spec card, Design step, help panels, exports and import, end-to-end and accessibility tests.
  4. Evaluation, documentation and video. Benchmark, the pre-registered rule, harness, scoring, decision records, user guide, architecture page, process figure, STE check, introduction video (English and Spanish), replication sync.

19References

  • Block, R. M., and Mee, R. W. (2005). Resolution IV designs with 128 runs. Journal of Quality Technology, 37(4), 282-293. Corrigenda (2006), 38, 196.
  • Box, G. E. P., and Meyer, R. D. (1986). An analysis for unreplicated fractional factorials. Technometrics, 28(1), 11-18. https://doi.org/10.1080/00401706.1986.10488093
  • Chen, J., Sun, D. X., and Wu, C. F. J. (1993). A catalogue of two-level and three-level fractional factorial designs with small runs. International Statistical Review, 61(1), 131-145.
  • Groemping, U. (2014). R package FrF2 for creating and analyzing fractional factorial 2-level designs. Journal of Statistical Software, 56(1), 1-56. https://doi.org/10.18637/jss.v056.i01
  • Groemping, U. (2024). RcmdrPlugin.DoE: R Commander plugin for (industrial) design of experiments (R package version 0.12-6). https://cran.r-project.org/package=RcmdrPlugin.DoE
  • Groemping, U. (2025). DoE.wrapper: Wrapper package for design of experiments functionality (R package version 0.13). https://cran.r-project.org/package=DoE.wrapper
  • Groemping, U. (n.d.). Software for design of experiments (Versuchsplanung). Berliner Hochschule für Technik. Read on 2026-10-19. https://prof.bht-berlin.de/groemping/software/versuchsplanung
  • Hamada, M., and Wu, C. F. J. (1992). Analysis of designed experiments with complex aliasing. Journal of Quality Technology, 24(3), 130-137. https://doi.org/10.1080/00224065.1992.11979383
  • Harrower, M., and Brewer, C. A. (2003). ColorBrewer.org: An online tool for selecting colour schemes for maps. The Cartographic Journal, 40(1), 27-37.
  • Li, X., Sudarsanam, N., and Frey, D. D. (2006). Regularities in data from factorial experiments. Complexity, 11(5), 32-45. https://doi.org/10.1002/cplx.20123
  • Machado, G. M., Oliveira, M. M., and Fernandes, L. A. F. (2009). A physiologically-based model for simulation of color vision deficiency. IEEE Transactions on Visualization and Computer Graphics, 15(6), 1291-1298.
  • Mee, R. W. (2009). A comprehensive guide to factorial two-level experimentation. Springer. https://doi.org/10.1007/b105081
  • Megahed, F. M., Chen, Y.-J., Ferris, J. A., Resatar, C., Ross, K., Lee, Y., and Jones-Farmer, L. A. (2024). ChatISA: A prompt-engineered, in-house multi-modal generative AI chatbot for information systems education. arXiv:2407.15010 (v2, May 2025). Source code: https://github.com/fmegahed/chatisa
  • Ockuly, R. A., Weese, M. L., Smucker, B. J., Edwards, D. J., and Chang, L. (2017). Response surface experiments: A meta-analysis. Chemometrics and Intelligent Laboratory Systems, 164, 64-75. https://doi.org/10.1016/j.chemolab.2017.03.009
  • Ottosson, B. (2020). A perceptual color space for image processing. https://bottosson.github.io/posts/oklab/
  • Ryan, K. J., and Bulutoglu, D. A. (2010). Minimum aberration fractional factorial designs with large N. Technometrics, 52(2), 250-255. https://doi.org/10.1198/TECH.2010.08020
  • Vazquez, A. R., Rother, K. M., and Charles-Gonzalez, M. V. (2026). A systematic assessment of large language models for constructing two-level fractional factorial designs. Quality Engineering. https://doi.org/10.1080/08982112.2026.2625951
  • Wu, C. F. J., and Hamada, M. S. (2021). Experiments: Planning, analysis, and optimization (3rd ed.). Wiley. https://doi.org/10.1002/9781119470007
  • Xu, H. (2009). Algorithmic construction of efficient fractional factorial designs with large run sizes. Technometrics, 51(3), 262-277. https://doi.org/10.1198/TECH.2009.07120
  • Xu, H., and Wu, C. F. J. (2001). Generalized minimum aberration for asymmetrical fractional factorial designs. Annals of Statistics, 29(4), 1066-1077. https://doi.org/10.1214/aos/1013699993
  • Ying, D. D., Vazquez, A. R., and Xu, H. (2026). Prompt engineering using order-of-addition experiments: An application to generating two-level fractional factorial designs. arXiv:2607.05537.
  • Software and documentation: Claude Code; superpowers; TypeSafe documentation; ASD-STE100; hf_arxiv_control_charts.