docs: reorganise -- current reference gathered, finished work archived, superseded and dead ideas marked as such

docs/CLAUDE.md Phase 2, 2026-10-14.  All moves by git mv; every archived
file carries a header saying what it is, why, and where to look instead.

- docs/reference/ (new): roadmap and versioning policy, M7.1, word-ACL
  design, kernel args, hosted acceptance test, dictionary, primitives,
  ontology, L8 table -- previously spread over docs/, docs/lithosananke/
  and docs/03-architecture/.
- docs/working/archive/historical/: finished work (session plan, test-gap
  audit, birthing plan, fix write-ups, the January architecture draft).
- docs/working/archive/superseded/: the Hermes-VM Tripod docs and July
  Hermes designs (-> FABRIC-3.5/3.6), the StarForth roadmap, every working
  doc already flagged superseded or obsolete.
- docs/working/archive/dead/: the hal_* target contract (never adopted),
  L4Re, metrics-and-knobs.
- Papers and proposals into docs/working/papers/.
- References rewritten across the repo (not logs/, not docs/patent/);
  CLAUDE.md's documentation section rewritten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 16:03:56 -04:00
co-authored by Claude Opus 5.5
parent 1a4b163861
commit 7aed588f78
116 changed files with 305 additions and 175 deletions
@@ -0,0 +1,265 @@
> **SUPERSEDED (docs triage 2026-10-14).** The 2^6 factorial DoE guide, flagged obsolete 2026-10-09.
> Instead: experiments/bare_metal/README.md for the DoE as it runs now. Moved here from `docs/working/experiments/02-experiments/factorial-doe/guide.md`.
<!-- Moved from docs/02-experiments/factorial-doe/guide.md to docs/working/archive/superseded/factorial-doe/guide.md on 2026-06-16 (docs reorg Phase 2) -->
> **⚠ OBSOLETE (flagged 2026-10-09).** Describes the retired per-loop Makefile-toggle
> architecture, replaced by the L8 Jacquard runtime mode selector. Kept for historical record.
# StarForth Complete 2^6 Factorial Design of Experiments
## Overview
**One-and-done comprehensive factorial testing** - collect all data systematically, analyze separately.
This guide describes how to run a **complete 2^6 factorial design of experiments** across all 6 feedback loops, yielding:
- **64 unique configurations** (all binary combinations)
- **1,920+ runs** (30 samples per configuration)
- **Single unified dataset** for factorial analysis
## The Why: Factorial DoE
Instead of incrementally tuning parameters, we collect **comprehensive experimental data** in one go:
### Traditional Approach (Old)
- Run baseline
- Run with Loop #1
- Run with Loops #1-2
- Run with Loops #1-3
- ... (sequential, incremental)
- **Problem:** Can't see interactions, trade-offs, or surprises
### Factorial Approach (New)
- Run ALL 2^6 = 64 combinations in randomized order
- Collect all data at once
- Analyze factorial effects, interactions, and main effects
- **Advantage:** Complete picture of how loops interact
## The 6 Feedback Loops
Each loop is a binary toggle in the Makefile:
| Loop | Makefile Flag | Purpose |
|------|---|---|
| **#1** | `ENABLE_LOOP_1_HEAT_TRACKING` | Count word execution frequency |
| **#2** | `ENABLE_LOOP_2_ROLLING_WINDOW` | Capture execution history (circular buffer) |
| **#3** | `ENABLE_LOOP_3_LINEAR_DECAY` | Age words by exponential decay over time |
| **#4** | `ENABLE_LOOP_4_PIPELINING_METRICS` | Track word-to-word transitions |
| **#5** | `ENABLE_LOOP_5_WINDOW_INFERENCE` | Infer optimal window width (Levene's test) |
| **#6** | `ENABLE_LOOP_6_DECAY_INFERENCE` | Infer decay slope via linear regression |
## Configuration Naming
Each of 64 configurations is named by its loop status:
```
L1_L2_L3_L4_L5_L6
Where each digit is 0 (OFF) or 1 (ON)
Examples:
000000 = Baseline (all loops OFF - pure FORTH-79)
000001 = Only heat tracking
111110 = All except decay inference
111111 = All loops ON (likely optimal)
101010 = Alternating pattern (for research)
```
## Quick Start
### Minimal Test (validate script)
```bash
./scripts/run_factorial_doe.sh --runs-per-config 1 TEST_RUN
# 64 builds × 1 run = 64 total runs
# Runtime: ~30-45 minutes
# Output: /home/rajames/CLionProjects/StarForth-DoE/experiments/TEST_RUN/
```
### Standard Comprehensive Run
```bash
./scripts/run_factorial_doe.sh --runs-per-config 30 2025_11_19_FACTORIAL
# 64 builds × 30 runs = 1,920 total runs
# Runtime: ~2-4 hours
# Output: /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FACTORIAL/
```
### High-Precision Run
```bash
./scripts/run_factorial_doe.sh --runs-per-config 100 HIGH_PRECISION_DOE
# 64 builds × 100 runs = 6,400 total runs
# Runtime: ~6-12 hours
# Output: /home/rajames/CLionProjects/StarForth-DoE/experiments/HIGH_PRECISION_DOE/
```
## Output Structure
```
/home/rajames/CLionProjects/StarForth-DoE/experiments/<EXPERIMENT_LABEL>/
├── experiment_results.csv # All measurements (1920+ rows)
├── experiment_summary.txt # Timing, metadata, statistics
├── configuration_manifest.txt # All 64 configs documented
├── test_matrix.txt # Randomized execution order
└── run_logs/
├── 000000_run_1.log
├── 000000_run_2.log
├── 000001_run_1.log
├── ...
└── 111111_run_30.log # 1,920 total log files
```
## CSV Schema
Each row in `experiment_results.csv` contains:
```
timestamp,configuration,run_number,
<35+ metrics from test harness>,
enable_loop_1_heat_tracking,
enable_loop_2_rolling_window,
enable_loop_3_linear_decay,
enable_loop_4_pipelining_metrics,
enable_loop_5_window_inference,
enable_loop_6_decay_inference
```
This lets you correlate every metric against every loop combination.
## Analysis Strategy
After collection, analyze in the separate `StarForth-DoE` repository:
### Step 1: Load Data
```python
import pandas as pd
df = pd.read_csv("experiment_results.csv")
print(df.shape) # Should be (1920, 38+)
print(df.columns)
```
### Step 2: Separate Metrics from Factors
```python
factor_cols = ['enable_loop_1_heat_tracking', ..., 'enable_loop_6_decay_inference']
metric_cols = ['total_lookups', 'cache_hit_percent', ..., 'vm_workload_duration_ns_q48']
factors = df[factor_cols]
metrics = df[metric_cols]
```
### Step 3: Factorial Analysis
```python
# Main effects: What's the average change when Loop X goes from 0→1?
main_effects = {}
for loop in factor_cols:
main_effects[loop] = metrics[factors[loop]==1].mean() - metrics[factors[loop]==0].mean()
# Interactions: Do loops work better/worse together?
# Can use statsmodels.formula.api for ANOVA/regression
# Optimal subset: Which combinations of loops give best throughput?
best_configs = df.nlargest(10, 'vm_workload_duration_ns_q48')
```
## Key Design Choices
### 1. **Rebuild Every Pass** ✓
- Each configuration requires a `make clean && make`
- Ensures clean, isolated state
- No cross-contamination
- True ground truth for each variant
### 2. **Randomized Execution**
- All 1,920 runs randomized into single matrix (not 64 separate runs)
- Prevents thermal ramp, temporal bias, or systematic trends
- DoE principle: randomization eliminates confounds
### 3. **Full Factorial** (not fractional)
- Testing ALL 2^6 = 64 combinations
- Can detect unexpected interactions
- Most expensive, most informative
### 4. **One-and-Done Collection**
- Single experiment, all data
- No progressive tuning during collection
- Separates measurement from analysis (good practice)
## Expected Results
### Hypothetical Output
Assuming typical performance distribution:
```
Configuration | Avg Time (ns) | Speed vs Baseline
─────────────────────────────────────────────────
000000 (base) | 10,000,000 | 1.0x
000001 (L1) | 9,950,000 | 1.005x
111111 (all) | 8,500,000 | 1.176x ← Likely best
```
### Expected Patterns
1. **Loop #1 (heat tracking)**: ~2-5% improvement alone
2. **Loop #2 (rolling window)**: ~1-3% improvement (depends on L1)
3. **Loops #3-6**: Increasingly synergistic (work better together)
4. **Interactions**: Loop #5 + #6 likely synergistic (inference loops)
## Troubleshooting
### Build Fails for a Configuration
```bash
# Check specific config build log
cat /home/rajames/CLionProjects/StarForth-DoE/experiments/<LABEL>/run_logs/build_<CONFIG>.log
```
### Test Harness Crashes on Some Configs
- Check if loop combination is invalid (e.g., Loop #5 without Loop #2)
- Verify Makefile flags are correctly parsed
- See: `include/vm.h` for interdependencies
### Results Look Suspicious
- Check `test_matrix.txt` - ensure randomization is present
- Verify CSV row counts match expected total
- Check for missing runs in log directory
## Performance Notes
### Timing Estimates
- **Minimal (1 run/config)**: 30-45 minutes
- **Standard (30 runs/config)**: 2-4 hours
- **High-precision (100 runs/config)**: 6-12 hours
- **Depends on:** CPU speed, disk I/O, test harness overhead
### Optimization
- Run overnight for high-precision experiments
- Use `screen` or `tmux` to keep session alive
- Monitor disk space (~100 MB for results + logs)
## Next Steps
1. **Run the experiment:**
```bash
./scripts/run_factorial_doe.sh 2025_11_19_COMPLETE_FACTORIAL
```
2. **Monitor progress:**
```bash
tail -f /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_COMPLETE_FACTORIAL/experiment_summary.txt
```
3. **Move to analysis repo** (once complete):
```bash
cp -r /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_COMPLETE_FACTORIAL \
/home/rajames/CLionProjects/StarForth-DoE-Analysis/data/
cd /home/rajames/CLionProjects/StarForth-DoE-Analysis
python3 analyze_factorial.py data/2025_11_19_COMPLETE_FACTORIAL/experiment_results.csv
```
4. **Generate reports:**
- Main effects plots
- Interaction matrices
- Pareto optimal configurations
- Recommendations for production builds
---
**Version:** 1.0
**Last Updated:** 2025-11-19
**Author:** Claude Code (with Robert A. James)
@@ -0,0 +1,404 @@
> **SUPERSEDED (docs triage 2026-10-14).** The 2^6 factorial DoE guide, flagged obsolete 2026-10-09.
> Instead: experiments/bare_metal/README.md for the DoE as it runs now. Moved here from `docs/working/experiments/02-experiments/factorial-doe/incompatible-configs.md`.
<!-- Moved from docs/02-experiments/factorial-doe/incompatible-configs.md to docs/working/archive/superseded/factorial-doe/incompatible-configs.md on 2026-06-16 (docs reorg Phase 2) -->
> **⚠ OBSOLETE (flagged 2026-10-09).** Build-time incompatibility handling for the retired 2^6
> toggle experiment, replaced by the L8 Jacquard mode selector. Kept for historical record.
# Handling Incompatible Configurations in Factorial DoE
## Overview
Your intuition was correct: **some loop combinations can't coexist**. Rather than failing the entire experiment, the updated script treats incompatibility as valuable data.
This document explains how the script detects and records incompatible configurations during the factorial experiment.
---
## What is an Incompatible Configuration?
An incompatible configuration is a combination of feedback loop toggles that:
1. **Fails to compile** - Makefile target produces build errors
2. **Causes StarForth to crash** - Binary exits abnormally (segfault, signal, etc.)
3. **Produces invalid output** - Test harness runs but produces no metrics
Examples (hypothetical):
- Loop 5 (window inference) without Loop 2 (rolling window) = no data to infer from
- Loop 6 (decay inference) without Loop 3 (linear decay) = no slope to measure
- Certain combinations trigger memory conflicts or uninitialized states
---
## How the Script Handles It
### Detection Strategy
**Build Phase:**
```
Configuration X attempted
├─ make TARGET=fastest ENABLE_LOOP_1=1 ...ENABLE_LOOP_6=0
├─ Check exit code
├─ If success: mark as "OK", proceed to testing
└─ If failure: mark as "BUILD_FAILED", skip all runs for this config
```
**Execution Phase:**
```
Run configuration X, iteration N
├─ Execute: ./starforth --doe-experiment
├─ Check exit code
├─ Try to extract metrics from output
├─ If success: mark as "OK", record metrics
└─ If failure: mark as "CRASH", record incompatibility
```
### CSV Recording
Incompatible configurations are recorded with status flags:
**Successful run (viable config):**
```
timestamp,configuration,run_number,build_status,run_status,
2025-11-19T10:30:45,1_1_0_1_0_0,5,OK,OK,
<35+ metrics>,1,1,0,1,0,0
```
**Build failure (incompatible):**
```
timestamp,configuration,run_number,build_status,run_status,
2025-11-19T10:35:20,0_1_1_1_1_0,1,BUILD_FAILED,<skipped>,
<empty>,0,1,1,1,1,0
```
**Runtime crash (incompatible):**
```
timestamp,configuration,run_number,build_status,run_status,
2025-11-19T10:40:15,1_0_0_1_1_1,3,OK,CRASH,
<empty>,1,0,0,1,1,1
```
### Experiment Flow
The experiment **continues** when incompatibility is detected:
```
Run 1: Config A (OK) → Test completes, metrics recorded
Run 2: Config B (BUILD_FAILED) → Build fails, skip all runs for B, continue
Run 3: Config A (OK) → Test completes, metrics recorded
Run 4: Config C (CRASH) → Crashes, record as incompatible, continue
...
Run N: Config D (OK) → Test completes, metrics recorded
SUMMARY:
✓ Successful runs: 847/1920
✗ Failed configs: 17 (incompatible combinations detected)
✓ Experiment completed despite incompatibilities
```
---
## CSV Schema
### Two New Columns
| Column | Values | Meaning |
|--------|--------|---------|
| `build_status` | OK, BUILD_FAILED | Did Makefile compilation succeed? |
| `run_status` | OK, CRASH | Did StarForth execute without crashing? |
### Analysis Filter Rules
```python
import pandas as pd
df = pd.read_csv('experiment_results.csv')
# Only viable configurations
viable = df[(df['build_status'] == 'OK') & (df['run_status'] == 'OK')]
# Incompatible configs (at compile time)
build_failures = df[df['build_status'] == 'BUILD_FAILED']
# Incompatible configs (at runtime)
runtime_crashes = df[df['run_status'] == 'CRASH']
# All incompatible
incompatible = df[(df['build_status'] != 'OK') | (df['run_status'] != 'OK')]
```
---
## Interpreting Results
### Experiment Summary
After completion, you'll see:
```
═══════════════════════════════════════════════════════════
EXPERIMENT COMPLETE (with incompatibility detection)
═══════════════════════════════════════════════════════════
✓ Successful runs: 1847/1920
✓ Failed configurations (incompatible): 17
→ Incompatible configurations detected:
✗ 0_1_1_1_1_0 (BUILD_FAILED)
✗ 1_0_0_1_1_1 (CRASH)
✗ 0_1_0_1_1_1 (CRASH)
... (total 17)
→ These configs are marked in CSV with build_status or run_status
→ They represent configurations where loops cannot coexist without conflict
```
### What This Means
- **1847 successful runs** = viable, measurable configurations
- **17 incompatible** = design space constraints discovered
- **Experiment completed** = data collection succeeded despite incompatibilities
- **CSV includes both** = full picture of parameter space
---
## Analysis Examples
### Example 1: Summary by Viability
```python
import pandas as pd
df = pd.read_csv('experiment_results.csv')
# Count by status
viable = len(df[(df['build_status'] == 'OK') & (df['run_status'] == 'OK')])
build_fail = len(df[df['build_status'] == 'BUILD_FAILED'].drop_duplicates('configuration'))
runtime_crash = len(df[df['run_status'] == 'CRASH'].drop_duplicates('configuration'))
print(f"Viable configurations: {viable} runs")
print(f"Build failures: {build_fail} configurations")
print(f"Runtime crashes: {runtime_crash} configurations")
print(f"Total tested: {64} configurations, {64*30} runs")
print(f"Success rate: {viable}/{len(df)} = {100*viable/len(df):.1f}%")
```
Expected output:
```
Viable configurations: 1847 runs
Build failures: 5 configurations
Runtime crashes: 12 configurations
Total tested: 64 configurations, 1920 runs
Success rate: 1847/1920 = 96.2%
```
### Example 2: Identify Problematic Loop Combinations
```python
# Find configs that always crash
crashes = df[df['run_status'] == 'CRASH'].drop_duplicates('configuration')
print("Configurations that crash:")
for config in crashes['configuration']:
parts = config.split('_')
loops_on = [f"Loop{i+1}" for i, bit in enumerate(parts) if bit == '1']
print(f" {config}: {', '.join(loops_on) or 'None'}")
```
Expected output:
```
Configurations that crash:
0_1_1_1_1_0: Loop2, Loop3, Loop4, Loop5
1_0_0_1_1_1: Loop1, Loop4, Loop5, Loop6
0_1_0_1_1_1: Loop2, Loop4, Loop5, Loop6
... etc
```
**Insight:** Loop 5 (window inference) appears in many crashes → suggests window inference has prerequisites or conflicts.
### Example 3: Feasibility Matrix
```python
# Which loop combinations are feasible?
df_viable = df[(df['build_status'] == 'OK') & (df['run_status'] == 'OK')].copy()
# For each config, mark as viable (1) or not (0)
feasible = {}
for config in df['configuration'].unique():
is_viable = len(df_viable[df_viable['configuration'] == config]) > 0
feasible[config] = 1 if is_viable else 0
# Show as binary matrix
print("Feasibility (1=viable, 0=incompatible):")
for i in range(64):
config = f"{i%2}_{(i//2)%2}_{(i//4)%2}_{(i//8)%2}_{(i//16)%2}_{(i//32)%2}"
print(f"{config}: {'✓' if feasible[config] else '✗'}")
```
Result: Feasibility map of 64 configurations for maintenance and design decisions.
---
## Maintenance Insights
### Why Some Combinations Are Incompatible
Common reasons:
1. **Missing Prerequisites:**
- Loop 5 (window inference) needs Loop 2 (rolling window) data
- Loop 6 (decay inference) needs Loop 3 (linear decay) to measure
2. **Memory/Resource Conflicts:**
- Multiple loops allocating same memory region
- Circular dependencies in initialization
3. **Semantic Contradictions:**
- Loop X disables feature that Loop Y requires
- Incompatible macro definitions
4. **Bugs in Specific Combinations:**
- Race conditions appearing only with certain feature combinations
- Uninitialized state when paths not taken
### Using This Information
**For Future Development:**
```
Findings: Loop 5 incompatible without Loop 2
→ Check: Does window inference code assume rolling window exists?
→ Action: Either add guard (if !LOOP_5 without LOOP_2) or document prerequisite
→ Test: Add compile-time or runtime check
```
**For Optimization:**
```
Result: All configs with Loop 6 crash if Loop 1 is OFF
→ Issue: Decay inference needs heat tracking for slope calculation
→ Fix: Add LOOP_1_REQUIRED_BY_LOOP_6 guard in code
→ Verify: Re-run factorial (expect fewer crashes)
```
**For Production:**
```
Feasible subset: {0_0_0_0_0_0, 1_1_0_0_0_0, 1_1_1_0_0_0, 1_1_1_1_1_1}
→ Recommendation: Use 1_1_1_1_1_1 (all compatible, best performance)
→ Fallback: Use 1_1_0_0_0_0 (compatible, simpler)
→ Baseline: Use 0_0_0_0_0_0 (no feedback, minimal overhead)
```
---
## Next Steps
1. **Run the experiment** to completion (incompatibilities are discovered organically)
2. **Analyze the CSV** to identify which configs are viable
3. **Examine incompatible configs** to understand why they fail
4. **Document prerequisites** (which loops require others)
5. **Fix or guard** the code to eliminate incompatibilities
6. **Re-run** experiment to validate fixes
---
## Technical Details
### Build Failure Detection
```bash
if make TARGET=fastest ENABLE_LOOP_1=1 ... > build_log 2>&1; then
# Build successful
BUILD_STATUS="OK"
else
# Build failed - mark incompatible
BUILD_STATUS="BUILD_FAILED"
# Skip all runs for this config
continue
fi
```
### Runtime Crash Detection
```bash
if "${BINARY}" --doe-experiment > run_log 2>&1; then
# Binary executed (exit code 0)
if extract_csv_row(run_log) succeeds:
RUN_STATUS="OK"
else:
RUN_STATUS="CRASH" # Binary ran but no output
else
# Binary crashed (non-zero exit)
RUN_STATUS="CRASH"
fi
```
### CSV Recording
```bash
# Viable run
printf '%s,%s,%s,%s,%s,%s,%s\n' \
"${timestamp}" "${config}" "${run_num}" \
"OK" "OK" \
"${csv_row}" "${flags}" >> results_run_01_2025_12_08.csv
# Incompatible run
printf '%s,%s,%s,%s,%s,%s\n' \
"${timestamp}" "${config}" "${run_num}" \
"${build_status}" "${run_status}" \
"${flags}" >> results_run_01_2025_12_08.csv
```
---
## Example: Real Incompatibility
**Scenario:** Loop 5 (window inference) without Loop 2 (rolling window)
```c
// Loop 5: Window Inference Code
void vm_tick_inference_engine(VM *vm) {
// Try to infer window width from rolling window
RollingWindowOfTruth *window = &vm->rolling_window; // LOOP_2 data
// BUG: If LOOP_2 is OFF, window is uninitialized!
uint32_t window_pos = window->window_pos; // CRASH: uninitialized read
}
```
**Symptom in CSV:**
```
Configuration 0_0_0_0_1_0 marked as CRASH
Loop1=0, Loop2=0, Loop3=0, Loop4=0, Loop5=1, Loop6=0
↑ ↑
Missing prerequisite Problematic loop
```
**Fix:**
```c
// Add guard in code
#if ENABLE_LOOP_5_WINDOW_INFERENCE
#if !ENABLE_LOOP_2_ROLLING_WINDOW
#error "Loop 5 requires Loop 2: window inference needs rolling window data"
#endif
#endif
```
**Result after fix:** Configuration 0_0_0_0_1_0 removed from viable set (prevented at compile time), reduces crash count.
---
## Summary
| Aspect | Approach |
|--------|----------|
| **Detection** | Build exit codes + runtime crash detection |
| **Recording** | New `build_status` and `run_status` columns |
| **Handling** | Skip incompatible config, continue experiment |
| **Impact** | Partial dataset (viable configs) + incompatibility map |
| **Analysis** | Filter by status, identify patterns |
| **Action** | Fix code, re-run, measure improvement |
This design enables discovering incompatibilities without sacrificing experimental continuity.
---
**Version:** 1.0
**Last Updated:** 2025-11-19
**Status:** Integrated into run_factorial_doe.sh
@@ -0,0 +1,271 @@
> **SUPERSEDED (docs triage 2026-10-14).** The 2^6 factorial DoE guide, flagged obsolete 2026-10-09.
> Instead: experiments/bare_metal/README.md for the DoE as it runs now. Moved here from `docs/working/experiments/02-experiments/factorial-doe/index.md`.
<!-- Moved from docs/02-experiments/factorial-doe/index.md to docs/working/archive/superseded/factorial-doe/index.md on 2026-06-16 (docs reorg Phase 2) -->
> **⚠ OBSOLETE (flagged 2026-10-09).** Index for the retired 2^6 factorial toggle
> architecture, replaced by the L8 Jacquard mode selector. Kept for historical record.
# StarForth Complete 2^6 Factorial DoE - Documentation Index
## Overview
This is a **one-and-done comprehensive factorial design of experiments** to systematically test all 64 possible combinations of 6 feedback loops.
**Key insight:** Don't toggle back-and-forth. Instead, systematically test ALL 2^6 combinations in a single experiment, then analyze the results afterward.
## Documentation Structure
### 1. **START HERE** 📋
- **File:** `docs/QUICK_START_FACTORIAL_DoE.md`
- **Purpose:** Entry point for quick reference
- **Read time:** 5 minutes
- **Contains:**
- 3 command options (quick/standard/high-precision)
- Time estimates
- What to expect during execution
- Basic troubleshooting
### 2. **Complete Guide** 📚
- **File:** `docs/FACTORIAL_DoE_GUIDE.md`
- **Purpose:** Full design documentation and rationale
- **Read time:** 20-30 minutes
- **Contains:**
- Why factorial DoE (vs. incremental tuning)
- 6 feedback loop definitions
- Configuration naming scheme (0_0_0_0_0_0 → 1_1_1_1_1_1)
- Design choices explained
- Expected results and patterns
- Troubleshooting guide
- Performance notes
### 3. **Analysis Workflow** 🔍
- **File:** `docs/FACTORIAL_DoE_ANALYSIS_WORKFLOW.md`
- **Purpose:** End-to-end pipeline from collection to insights
- **Read time:** 15-20 minutes (or 1-2 hours if coding along)
- **Contains:**
- Phase 1: Data collection (run script)
- Phase 2: Data transfer (to analysis repo)
- Phase 3: Statistical analysis (main effects, interactions)
- Phase 4: Reporting (generating insights)
- Python code examples:
* Load data and validate
* Compute main effects (individual loop impacts)
* Detect interactions (loop synergies)
* Optimize configuration subset
* Visualization code
- Example report structure
- Checklist for completion
### 4. **Main Script** ⚙️
- **File:** `scripts/run_factorial_doe.sh`
- **Purpose:** Executable for running the entire experiment
- **Read time:** 10 minutes (code + comments)
- **Contains:**
- Generates all 64 configurations
- Rebuilds for each unique configuration
- Randomizes execution order (1,920+ runs)
- Collects metrics to CSV
- Full instrumentation and progress reporting
---
## Reading Guide by Use Case
### "I just want to run the experiment"
1. Read: `QUICK_START_FACTORIAL_DoE.md` (5 min)
2. Execute: Choose command option (quick/standard/high-precision)
3. Wait: 30 min - 12 hours depending on option
4. Done!
### "I want to understand the design before running"
1. Read: `QUICK_START_FACTORIAL_DoE.md` (5 min)
2. Read: `FACTORIAL_DoE_GUIDE.md` (30 min)
3. Execute: Run with confidence
4. Analyze: Follow `FACTORIAL_DoE_ANALYSIS_WORKFLOW.md`
### "I need to analyze the results"
1. Read: `QUICK_START_FACTORIAL_DoE.md` → understand naming
2. Read: `FACTORIAL_DoE_ANALYSIS_WORKFLOW.md` → statistical methods
3. Code along: Use Python examples in Analysis Workflow
4. Interpret: Reference `FACTORIAL_DoE_GUIDE.md` for expected patterns
### "I want complete understanding"
Read in order:
1. `QUICK_START_FACTORIAL_DoE.md` (overview)
2. `FACTORIAL_DoE_GUIDE.md` (design rationale)
3. `scripts/run_factorial_doe.sh` (implementation)
4. `FACTORIAL_DoE_ANALYSIS_WORKFLOW.md` (analysis methods)
---
## Quick Command Reference
### Run Experiment
```bash
# Option A: Quick validation (30 min)
./scripts/run_factorial_doe.sh --runs-per-config 1 TEST_RUN
# Option B: Standard production (2-4 hours)
./scripts/run_factorial_doe.sh --runs-per-config 30 2025_11_19_FULL_FACTORIAL
# Option C: High-precision overnight (6-12 hours)
./scripts/run_factorial_doe.sh --runs-per-config 100 HIGH_PRECISION_FACTORIAL
```
### Monitor Progress
```bash
# Check results_run_01_2025_12_08 CSV growth
watch -n 5 'wc -l /path/to/experiment_results.csv'
# View summary
tail /path/to/experiment_summary.txt
# Count completed configurations
ls /path/to/run_logs/build_*.log | wc -l
```
### Analyze Results
```bash
# Load and analyze in Python
cd /path/to/StarForth-DoE-Analysis
python3 << 'EOF'
import pandas as pd
df = pd.read_csv('data/2025_11_19_FULL_FACTORIAL/experiment_results.csv')
print(f"Loaded {len(df)} runs")
# See FACTORIAL_DoE_ANALYSIS_WORKFLOW.md for full analysis code
EOF
```
---
## Key Concepts
### 64 Configurations
Each configuration is a unique combination of 6 binary factors:
- **0_0_0_0_0_0** = Baseline (all loops OFF)
- **1_0_0_0_0_0** = Only heat tracking
- **1_1_0_0_0_0** = Heat + rolling window
- ...
- **1_1_1_1_1_1** = All loops ON (current optimal)
### Randomized Execution
All 1,920+ runs (64 configs × 30 samples) are randomized into a single execution matrix.
- Eliminates temporal bias
- Prevents thermal ramp (if CPU heats during night)
- Proper DoE methodology
### One-and-Done Collection
Collect all data in single experiment, analyze separately.
- No tuning during collection (avoid bias)
- Single pass through parameter space
- Separates measurement from analysis
### Main Effects
Individual impact of each loop:
```
Loop #1: Loop turns ON, average metric changes by X%
Loop #2: Loop turns ON, average metric changes by Y%
... etc
```
### Interactions
How loops work together (amplify or suppress each other):
```
Loop #1 + Loop #2: Do they work better together than independently?
```
---
## Files at a Glance
| File | Size | Purpose |
|------|------|---------|
| `scripts/run_factorial_doe.sh` | 19 KB | Main executable script |
| `docs/QUICK_START_FACTORIAL_DoE.md` | 4.9 KB | Quick reference |
| `docs/FACTORIAL_DoE_GUIDE.md` | 8.0 KB | Design documentation |
| `docs/FACTORIAL_DoE_ANALYSIS_WORKFLOW.md` | 9.6 KB | Analysis pipeline |
| `docs/FACTORIAL_DoE_INDEX.md` | This file | Documentation index |
---
## Execution Timeline
### Phase 1: Preparation (5-10 min)
- Read `QUICK_START_FACTORIAL_DoE.md`
- Choose execution option
- Run command
### Phase 2: Collection (30 min - 12 hours)
- Script builds all 64 configs (as needed)
- Randomized execution of 1,920+ runs
- Metrics collected to CSV
- Progress shown every run
### Phase 3: Transfer (5 min)
- Copy results to analysis repo
- Verify file integrity
### Phase 4: Analysis (1-2 hours)
- Load CSV in Python
- Compute main effects
- Detect interactions
- Find optimal configurations
- Generate visualizations
### Phase 5: Reporting (1-2 hours)
- Summarize findings
- Create report
- Recommendations for production
**Total time:** Collection (2-4 hrs) + Analysis (2-4 hrs) = **4-8 hours**
---
## The Design Philosophy
### Problem Statement
How do we systematically understand the performance contribution and interactions of 6 interdependent feedback loops?
### Solution
**Complete 2^6 factorial design of experiments**
### Why This Approach
1. **Complete:** Tests all 64 combinations (no gaps)
2. **Systematic:** Proper experimental design methodology
3. **Separable:** Collection ≠ Analysis (reduces bias)
4. **Reproducible:** Randomized execution, full logging
5. **Scalable:** Single script, extensible to more factors
### Alternatives Rejected
- ❌ Incremental tuning ("baseline → +loop1 → +loop1+2"): Misses interactions
- ❌ Dynamic toggle without rebuild: Introduces state contamination
- ❌ Partial factorial: Misses key interactions
- ❌ One-at-a-time testing: Expensive and confounded
---
## Next Steps
1. **Read** `QUICK_START_FACTORIAL_DoE.md` (5 minutes)
2. **Decide** which execution option (quick/standard/precise)
3. **Run** the command and let it collect data
4. **Monitor** progress in another terminal
5. **Analyze** results using `FACTORIAL_DoE_ANALYSIS_WORKFLOW.md`
6. **Report** findings to stakeholders
---
## Questions?
- **"How long will this take?"** → See `QUICK_START_FACTORIAL_DoE.md`
- **"What does configuration X mean?"** → See `FACTORIAL_DoE_GUIDE.md`
- **"How do I analyze the results?"** → See `FACTORIAL_DoE_ANALYSIS_WORKFLOW.md`
- **"Why this approach?"** → See `FACTORIAL_DoE_GUIDE.md` - "The Why"
- **"How do I run it?"** → `./scripts/run_factorial_doe.sh`
---
**Version:** 1.0
**Created:** 2025-11-19
**Status:** Ready for production use
@@ -0,0 +1,158 @@
> **SUPERSEDED (docs triage 2026-10-14).** Quick start for the same 2^6 factorial DoE, flagged obsolete 2026-10-09.
> Instead: experiments/bare_metal/README.md. Moved here from `docs/working/architecture/getting-started/quick-start/factorial-doe.md`.
<!-- Moved from docs/01-getting-started/quick-start/factorial-doe.md to docs/working/archive/superseded/factorial-doe/quick-start.md on 2026-06-16 (docs reorg Phase 2) -->
> **⚠ OBSOLETE (flagged 2026-10-09).** Describes the retired per-loop `ENABLE_LOOP_1..6`
> compile-time toggle architecture and hardcoded local paths; the physics adaptation is now
> driven by the L8 Jacquard runtime mode selector. Kept for historical record.
# Quick Start: Complete 2^6 Factorial DoE
## TL;DR
Run a **complete, exhaustive 2^6 = 64 configuration experiment** in one go, collecting all data for later analysis.
## Three Command Options
### Option 1: Quick Validation (30 min)
Test the script and infrastructure:
```bash
./scripts/run_factorial_doe.sh --runs-per-config 1 QUICK_TEST
```
- 64 builds × 1 run = 64 total runs
- Fast feedback on whether setup works
- Output: `/home/rajames/CLionProjects/StarForth-DoE/experiments/QUICK_TEST/`
### Option 2: Standard Full DoE (2-4 hours)
Comprehensive factorial collection:
```bash
./scripts/run_factorial_doe.sh --runs-per-config 30 2025_11_19_FULL_FACTORIAL
```
- 64 builds × 30 runs = 1,920 total runs
- Good statistical power for main effects
- Standard production-grade experiment
- Output: `/home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/`
### Option 3: High-Precision Run (6-12 hours)
Maximum data for deep analysis:
```bash
./scripts/run_factorial_doe.sh --runs-per-config 100 HIGH_PRECISION_FACTORIAL
```
- 64 builds × 100 runs = 6,400 total runs
- Best for detecting subtle interactions
- Run overnight for best results
- Output: `/home/rajames/CLionProjects/StarForth-DoE/experiments/HIGH_PRECISION_FACTORIAL/`
## What Gets Generated
```
/home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/
├── experiment_results.csv ← All 1,920 rows of measurements
├── experiment_summary.txt ← Timing and metadata
├── configuration_manifest.txt ← All 64 configs listed
├── test_matrix.txt ← Randomized execution order
└── run_logs/
├── 0_0_0_0_0_0_run_1.log
├── 0_0_0_0_0_0_run_2.log
├── ...
└── 1_1_1_1_1_1_run_30.log
```
## What's Being Tested
6 **independent binary feedback loops**:
| Loop | Toggle | What It Does |
|------|--------|---|
| 1 | `ENABLE_LOOP_1_HEAT_TRACKING` | Count execution frequency |
| 2 | `ENABLE_LOOP_2_ROLLING_WINDOW` | Capture execution history |
| 3 | `ENABLE_LOOP_3_LINEAR_DECAY` | Age words over time |
| 4 | `ENABLE_LOOP_4_PIPELINING_METRICS` | Track word transitions |
| 5 | `ENABLE_LOOP_5_WINDOW_INFERENCE` | Infer window width |
| 6 | `ENABLE_LOOP_6_DECAY_INFERENCE` | Infer decay slope |
**All 2^6 = 64 combinations** tested:
- `0_0_0_0_0_0` = Baseline (all OFF)
- `1_0_0_0_0_0` = Only heat tracking
- `0_1_0_0_0_0` = Only rolling window
- ...
- `1_1_1_1_1_1` = All loops ON (current optimal)
## During Execution
You'll see progress like:
```
═══════════════════════════════════════════════════════════
STARFORTH COMPLETE 2^6 FACTORIAL DoE
═══════════════════════════════════════════════════════════
→ Factors: 6 feedback loops (LOOP_1 through LOOP_6)
→ Configurations: 2^6 = 64
→ Runs per config: 30
→ TOTAL RUNS: 1,920
→ Output: /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL
>>> Generating randomized test matrix...
✓ Test matrix generated
→ Run 1/1920 - config 0_1_0_1_1_0 #14...
✓ Run 1/1920 completed (3s)
→ Run 2/1920 - config 1_1_1_0_0_1 #2...
✓ Run 2/1920 completed (2s)
...
```
The script:
1. **Builds** each of 64 configurations (rebuilds when config changes)
2. **Runs** tests in randomized order (no systematic bias)
3. **Collects** metrics to CSV
4. **Outputs** progress every run
## After Completion
Move to analysis repo to understand results:
```bash
cd /home/rajames/CLionProjects/StarForth-DoE-Analysis
python3 analyze_factorial.py \
data/2025_11_19_FULL_FACTORIAL/experiment_results.csv
```
Expected analysis outputs:
- **Main effects:** Which individual loops help most?
- **Interactions:** Do loops work better/worse together?
- **Optimal subset:** Best combination of loops?
- **Trade-offs:** Performance vs complexity?
## Key Design Decisions
✅ **Rebuild every pass** - ensures clean, isolated testing
✅ **Randomized execution** - eliminates temporal/thermal bias
✅ **Complete factorial** - captures all interactions
✅ **One-and-done** - collect all data, analyze later
## Estimated Time
| Runs/Config | Total | Time | When |
|---|---|---|---|
| 1 | 64 | 30-45 min | Quick test |
| 30 | 1,920 | 2-4 hours | Standard |
| 100 | 6,400 | 6-12 hours | Overnight |
Times depend on CPU, disk speed, and test harness overhead.
## Example Command
**Run it now:**
```bash
cd /home/rajames/CLionProjects/StarForth
./scripts/run_factorial_doe.sh 2025_11_19_FULL_FACTORIAL
```
**Monitor progress:**
```bash
tail -f /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/experiment_summary.txt
```
---
**Ready?** Run the command above and let the experiment collect comprehensive data for downstream analysis.
@@ -0,0 +1,300 @@
> **SUPERSEDED (docs triage 2026-10-14).** The 2^6 factorial DoE guide, flagged obsolete 2026-10-09.
> Instead: experiments/bare_metal/README.md for the DoE as it runs now. Moved here from `docs/working/experiments/02-experiments/factorial-doe/workflow.md`.
<!-- Moved from docs/02-experiments/factorial-doe/workflow.md to docs/working/archive/superseded/factorial-doe/workflow.md on 2026-06-16 (docs reorg Phase 2) -->
> **⚠ HISTORICAL (flagged 2026-10-09).** Documents the completed 2025-11-19 factorial
> campaign whose data informed the current L8 design; the toggle architecture it runs on is
> retired. Kept as a record.
# Factorial DoE Analysis Workflow
## End-to-End Process
```
StarForth Repo
└─ ./scripts/run_factorial_doe.sh
│
├─ Builds all 64 configurations
├─ Runs 1,920+ tests (randomized)
└─ Outputs: experiment_results.csv + logs
│
└─→ Copy to StarForth-DoE-Analysis repo
│
├─ Load CSV into Python/R
├─ Separate factors from metrics
├─ Compute main effects & interactions
├─ Identify optimal subsets
└─ Generate reports & visualizations
```
## Phase 1: Data Collection (StarForth Repo)
### Step 1: Run Experiment
```bash
cd /home/rajames/CLionProjects/StarForth
# Quick validation (optional)
./scripts/run_factorial_doe.sh --runs-per-config 1 TEST_01
# Full production run
./scripts/run_factorial_doe.sh --runs-per-config 30 2025_11_19_FULL_FACTORIAL
```
### Step 2: Wait for Completion
Monitor in another terminal:
```bash
watch -n 5 'wc -l /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/experiment_results.csv'
```
Expected progression:
- 0 min: 1 line (header)
- 30 min: ~500 lines
- 2 hours: ~1,500 lines
- 2.5 hours: 1,921 lines (complete)
### Step 3: Verify Completion
```bash
tail /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/experiment_results.csv
echo "---"
cat /home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL/experiment_summary.txt
```
## Phase 2: Data Transfer & Setup
### Step 1: Copy to Analysis Repo
```bash
RESULTS_DIR="/home/rajames/CLionProjects/StarForth-DoE/experiments/2025_11_19_FULL_FACTORIAL"
ANALYSIS_REPO="/home/rajames/CLionProjects/StarForth-DoE-Analysis"
mkdir -p "$ANALYSIS_REPO/data"
cp -r "$RESULTS_DIR" "$ANALYSIS_REPO/data/2025_11_19_FULL_FACTORIAL"
```
### Step 2: Verify Transfer
```bash
ls -lah "$ANALYSIS_REPO/data/2025_11_19_FULL_FACTORIAL/"
wc -l "$ANALYSIS_REPO/data/2025_11_19_FULL_FACTORIAL/experiment_results.csv"
```
## Phase 3: Analysis (StarForth-DoE-Analysis Repo)
### Load Data (Python)
```python
import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
# Load results_run_01_2025_12_08
df = pd.read_csv("data/2025_11_19_FULL_FACTORIAL/experiment_results.csv")
print(f"Loaded {len(df)} runs across {len(df.groupby('configuration'))} configurations")
# Separate factors and metrics
factors = df[['enable_loop_1_heat_tracking',
'enable_loop_2_rolling_window',
'enable_loop_3_linear_decay',
'enable_loop_4_pipelining_metrics',
'enable_loop_5_window_inference',
'enable_loop_6_decay_inference']]
metrics = df[['total_lookups', 'cache_hit_percent', 'vm_workload_duration_ns_q48', ...]]
print(f"Shape: {len(df)} rows × {len(df.columns)} columns")
print(f"Factors: {len(factors.columns)}")
print(f"Metrics: {len(metrics.columns)}")
```
### Main Effects Analysis
```python
# For each loop, compute average metric change when loop goes 0→1
main_effects = {}
for loop in factors.columns:
loop_name = loop.replace('enable_', '').replace('_', ' ').title()
metric_when_on = df[df[loop] == 1]['vm_workload_duration_ns_q48'].mean()
metric_when_off = df[df[loop] == 0]['vm_workload_duration_ns_q48'].mean()
effect = metric_when_on - metric_when_off
pct_change = 100 * (effect / metric_when_off)
main_effects[loop_name] = {
'effect': effect,
'pct_change': pct_change,
'on_mean': metric_when_on,
'off_mean': metric_when_off,
}
# Print sorted by impact
for loop, effect in sorted(main_effects.items(), key=lambda x: abs(x[1]['pct_change']), reverse=True):
print(f"{loop:30} {effect['pct_change']:+7.2f}% (ON: {effect['on_mean']:.0f}, OFF: {effect['off_mean']:.0f})")
```
Expected output:
```
Loop 6 Decay Inference +12.3% (ON: 8,800,000, OFF: 7,840,000)
Loop 5 Window Inference +8.5% (ON: 8,600,000, OFF: 7,920,000)
Loop 4 Pipelining Metrics +6.2% (ON: 8,400,000, OFF: 7,900,000)
Loop 3 Linear Decay +4.1% (ON: 8,200,000, OFF: 7,870,000)
Loop 2 Rolling Window +3.0% (ON: 8,100,000, OFF: 7,850,000)
Loop 1 Heat Tracking +2.1% (ON: 8,010,000, OFF: 7,850,000)
```
### Interaction Analysis
```python
# Two-way interactions: Do loops amplify/suppress each other?
interactions = {}
for i, loop_a in enumerate(factors.columns):
for j, loop_b in enumerate(factors.columns):
if i >= j:
continue # Only upper triangle
# Four cases: (0,0), (0,1), (1,0), (1,1)
case_00 = df[(df[loop_a] == 0) & (df[loop_b] == 0)]['vm_workload_duration_ns_q48'].mean()
case_01 = df[(df[loop_a] == 0) & (df[loop_b] == 1)]['vm_workload_duration_ns_q48'].mean()
case_10 = df[(df[loop_a] == 1) & (df[loop_b] == 0)]['vm_workload_duration_ns_q48'].mean()
case_11 = df[(df[loop_a] == 1) & (df[loop_b] == 1)]['vm_workload_duration_ns_q48'].mean()
# Interaction effect: (1,1) - (1,0) - (0,1) + (0,0)
interaction = (case_11 - case_10 - case_01 + case_00)
loop_a_name = loop_a.replace('enable_', '').replace('_', ' ')
loop_b_name = loop_b.replace('enable_', '').replace('_', ' ')
if abs(interaction) > 100000: # Only report large interactions
interactions[f"{loop_a_name} × {loop_b_name}"] = interaction
# Print sorted interactions
for pair, interaction in sorted(interactions.items(), key=lambda x: abs(x[1]), reverse=True):
print(f"{pair:40} {interaction:+12,.0f}")
```
### Optimal Configuration Search
```python
# Find best k configurations by performance metric
k = 10
best_configs = df.nlargest(k, 'vm_workload_duration_ns_q48')[
['configuration', 'vm_workload_duration_ns_q48', 'enable_loop_1_heat_tracking',
'enable_loop_2_rolling_window', 'enable_loop_3_linear_decay',
'enable_loop_4_pipelining_metrics', 'enable_loop_5_window_inference',
'enable_loop_6_decay_inference']
].drop_duplicates(subset=['configuration'])
print("Top 10 Configurations by Performance:")
print("─" * 100)
for idx, row in best_configs.iterrows():
loops = (
f"L1:{row['enable_loop_1_heat_tracking']} " +
f"L2:{row['enable_loop_2_rolling_window']} " +
f"L3:{row['enable_loop_3_linear_decay']} " +
f"L4:{row['enable_loop_4_pipelining_metrics']} " +
f"L5:{row['enable_loop_5_window_inference']} " +
f"L6:{row['enable_loop_6_decay_inference']}"
)
print(f"{row['configuration']:20} | {row['vm_workload_duration_ns_q48']:12,.0f} ns | {loops}")
```
### Visualization Example
```python
# Main effects plot
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
fig.suptitle('2^6 Factorial DoE Main Effects', fontsize=16)
loop_names = [f"Loop {i+1}" for i in range(6)]
metric_key = 'vm_workload_duration_ns_q48'
for idx, loop in enumerate(factors.columns):
ax = axes[idx // 3, idx % 3]
off_mean = df[df[loop] == 0][metric_key].mean()
on_mean = df[df[loop] == 1][metric_key].mean()
bars = ax.bar(['OFF', 'ON'], [off_mean, on_mean], color=['lightcoral', 'lightgreen'])
ax.set_ylabel('Workload Duration (ns)')
ax.set_title(f'{loop_names[idx]}')
ax.set_ylim([7000000, 10000000])
# Add value labels
for bar in bars:
height = bar.get_height()
ax.text(bar.get_x() + bar.get_width()/2., height,
f'{height/1e6:.1f}M', ha='center', va='bottom')
plt.tight_layout()
plt.savefig('main_effects.png', dpi=150)
print("Saved: main_effects.png")
```
## Phase 4: Reporting
### Key Outputs to Generate
1. **Main Effects Summary** (which loops matter most?)
- Table of individual loop impacts
- Sorted by effect size
2. **Interaction Matrix** (do loops amplify/suppress?)
- 6×6 table of two-way interactions
- Highlights synergies/conflicts
3. **Optimal Configuration** (best 10-20 subsets)
- Recommend top 3-5 production configs
- Show Pareto frontier (performance vs complexity)
4. **Statistical Summary**
- Variance by configuration
- Confidence intervals on estimates
- Regression model R²
### Example Report Structure
```markdown
# Factorial DoE Analysis Report - 2025-11-19
## Executive Summary
- Tested all 64 feedback loop combinations
- 1,920 experimental runs collected
- Key finding: Loops 5+6 show strong synergy (+18% combined)
## Main Effects
| Loop | Impact | Confidence | Recommendation |
|------|--------|-----------|---|
| Loop 6 (Decay Inference) | +12.3% | p<0.001 | **Enabled** |
| Loop 5 (Window Inference) | +8.5% | p<0.001 | **Enabled** |
| Loop 4 (Pipelining) | +6.2% | p<0.01 | Enabled |
| Loop 3 (Decay) | +4.1% | p<0.05 | Enabled |
| Loop 2 (Window) | +3.0% | p<0.05 | Enabled |
| Loop 1 (Heat) | +2.1% | p>0.05 | Optional |
## Recommended Configurations
1. **111111** (All loops): +30% vs baseline
2. **111110** (Except heat): +28% vs baseline, simpler
3. **011111** (Except heat, decay): +24% vs baseline
## Trade-off Analysis
- Full stack (111111): Best performance, highest code complexity
- Recommended (111110): 28% improvement, 95% of benefit
- Minimal set (001110): 18% improvement, 50% code overhead
---
```
## Checklist
- [ ] Run factorial DoE script to completion
- [ ] Verify 1,920 rows in experiment_results.csv
- [ ] Copy results to analysis repo
- [ ] Load data in Python/R
- [ ] Compute main effects (6 loops)
- [ ] Compute interactions (2-way or higher)
- [ ] Identify top 5-10 configurations
- [ ] Generate visualizations
- [ ] Write summary report
- [ ] Decide on production configuration
---
**Timeline:** Collection (2-4 hrs) + Analysis (2-4 hrs) = **6-8 hours total** for comprehensive factorial DoE.