Preregistered Analyses
The following sections implement the analysis plan in
OSF_PreReg.docx. The primary analyses are intent-to-treat:
manipulation-check failures are not excluded from the confirmatory
models. The experimental indicators are coded so that the reference
category is the human-operated U.S.-strike / Chinese-victim
condition.
Preregistered Analysis Data
comfort_levels <- c(
"Very uncomfortable",
"Somewhat uncomfortable",
"Neither comfortable or uncomfortable",
"Somewhat comfortable",
"Very comfortable"
)
education_levels <- c(
"Some high school or less",
"High school graduate or GED",
"Some college, no degree",
"2-year or associate degree",
"4-year or bachelor degree",
"Post-graduate degree"
)
income_levels <- c(
"Less than $15,000",
"$15,000 to under $50,000",
"$50,000 to under $75,000",
"$75,000 to under $100,000",
"$100,000 to under $150,000",
"$150,000 to under $200,000",
"More than $200,000"
)
age_levels <- c("18-29", "30-49", "50-64", "65+")
prereg_analysis_data <- survey %>%
filter(!is.na(consent),
grepl("I am 18 or older", consent),
!is.na(condition_agressor),
!is.na(condition_autonomy),
!is.na(intentionality)) %>%
mutate(
perceived_intentionality = as.numeric(intentionality),
escalation_likelihood = as.numeric(escalation),
escalation_justifiability = as.numeric(justified),
country_scenario = ifelse(condition_agressor == "China", 1, 0),
autonomous_ai = ifelse(condition_autonomy == "autonomous", 1, 0),
country_condition = ifelse(country_scenario == 1, "Chinese strike / U.S. victim", "U.S. strike / Chinese victim"),
weapons_condition = ifelse(autonomous_ai == 1, "Autonomous AI", "Human-operated"),
survey_weight = suppressWarnings(as.numeric(weight)),
us_ai_effectiveness = as.numeric(ai_us),
china_ai_effectiveness = as.numeric(ai_china),
southkorea_ai_effectiveness = as.numeric(ai_sk),
relative_china_us_ai = china_ai_effectiveness - us_ai_effectiveness,
age_group4 = factor(age_group4, levels = age_levels, ordered = TRUE),
age_ordinal = as.numeric(age_group4),
gender = factor(gender, levels = c("Male", "Female", "Other")),
education = factor(education, levels = education_levels, ordered = TRUE),
education_ordinal = as.numeric(education),
income = factor(income, levels = income_levels, ordered = TRUE),
income_ordinal = as.numeric(income),
race = factor(
race,
levels = c(
"White",
"Black or African-American",
"Asian or Asian-American",
"Native American or American Indian",
"Pacific Islander",
"Mixed race",
"Some other race"
)
),
race_white = factor(ifelse(race == "White", "White", "Non-white"),
levels = c("Non-white", "White")),
hispanic = factor(hispanic, levels = c("No", "Yes")),
metro = factor(metro, levels = c("Non-metro", "Metropolitan")),
ai_comfort = (
(match(comfort_doctor, comfort_levels) - 3) +
(match(comfort_news, comfort_levels) - 3) +
(match(comfort_banks, comfort_levels) - 3)
) / 3,
pid = case_when(
pid_base == "Democrat" ~ "Democrat",
pid_base == "Republican" ~ "Republican",
pid_base %in% c("Independent", "Other or none") &
pid_lean == "The Democratic Party" ~ "Democrat",
pid_base %in% c("Independent", "Other or none") &
pid_lean == "The Republican Party" ~ "Republican",
pid_base %in% c("Independent", "Other or none") &
(pid_lean == "Neither" | is.na(pid_lean)) ~ "Independent",
TRUE ~ NA_character_
),
pid = factor(pid, levels = c("Independent", "Democrat", "Republican")),
pid_republican = case_when(
pid == "Republican" ~ 1,
pid %in% c("Democrat", "Independent") ~ 0,
TRUE ~ NA_real_
),
gender_female = case_when(
gender == "Female" ~ 1,
gender %in% c("Male", "Other") ~ 0,
TRUE ~ NA_real_
),
comp_country_correct = case_when(
condition_agressor == "China" ~ compCheck_1 == "A Chinese weapons system",
condition_agressor == "US" ~ compCheck_1 == "A U.S. weapons system",
TRUE ~ NA
),
comp_autonomy_correct = case_when(
condition_autonomy == "autonomous" ~ grepl("fully autonomous", compCheck_2),
condition_autonomy == "human" ~ grepl("human-operated", compCheck_2),
TRUE ~ NA
),
comp_both_correct = comp_country_correct & comp_autonomy_correct
)
prereg_primary_data <- prereg_analysis_data %>%
filter(!is.na(perceived_intentionality),
!is.na(ai_comfort),
!is.na(relative_china_us_ai),
!is.na(pid_republican),
!is.na(age_ordinal),
!is.na(gender_female),
!is.na(education_ordinal),
!is.na(income_ordinal),
!is.na(race_white),
!is.na(hispanic),
!is.na(metro)) %>%
mutate(
ai_comfort_c = ai_comfort - mean(ai_comfort, na.rm = TRUE),
us_ai_effectiveness_c = us_ai_effectiveness - mean(us_ai_effectiveness, na.rm = TRUE),
china_ai_effectiveness_c = china_ai_effectiveness - mean(china_ai_effectiveness, na.rm = TRUE),
southkorea_ai_effectiveness_c = southkorea_ai_effectiveness - mean(southkorea_ai_effectiveness, na.rm = TRUE),
relative_china_us_ai_c = relative_china_us_ai - mean(relative_china_us_ai, na.rm = TRUE)
)
prereg_sample_summary <- data.frame(
sample = c("Assigned condition and primary outcome", "Covariate-complete primary model with demographics"),
n = c(nrow(prereg_analysis_data), nrow(prereg_primary_data))
)
kable(prereg_sample_summary, caption = "Preregistered analytic sample sizes.")
Preregistered analytic sample sizes.
| Assigned condition and primary outcome |
2935 |
| Covariate-complete primary model with demographics |
2833 |
Covariate Balance Checks
Coding note: these tables are diagnostics for the randomized design.
They are not used to decide whether to keep or drop covariates. The goal
is simply to show whether pretreatment characteristics look similar
across the four randomly assigned experimental cells.
balance_data <- prereg_analysis_data %>%
mutate(
condition_cell = paste(country_condition, weapons_condition, sep = " | "),
republican = pid_republican,
female = gender_female,
white = ifelse(race_white == "White", 1, 0),
hispanic_yes = ifelse(hispanic == "Yes", 1, 0),
metro_yes = ifelse(metro == "Metropolitan", 1, 0)
)
numeric_balance <- bind_rows(
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "AI comfort",
n = sum(!is.na(ai_comfort)),
mean = mean(ai_comfort, na.rm = TRUE),
sd = sd(ai_comfort, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "China minus U.S. AI effectiveness",
n = sum(!is.na(relative_china_us_ai)),
mean = mean(relative_china_us_ai, na.rm = TRUE),
sd = sd(relative_china_us_ai, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Age group (ordinal)",
n = sum(!is.na(age_ordinal)),
mean = mean(age_ordinal, na.rm = TRUE),
sd = sd(age_ordinal, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Education (ordinal)",
n = sum(!is.na(education_ordinal)),
mean = mean(education_ordinal, na.rm = TRUE),
sd = sd(education_ordinal, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Income (ordinal)",
n = sum(!is.na(income_ordinal)),
mean = mean(income_ordinal, na.rm = TRUE),
sd = sd(income_ordinal, na.rm = TRUE),
.groups = "drop"
)
) %>%
arrange(covariate, condition_cell)
binary_balance <- bind_rows(
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Republican",
n = sum(!is.na(republican)),
proportion = mean(republican, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Female",
n = sum(!is.na(female)),
proportion = mean(female, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "White",
n = sum(!is.na(white)),
proportion = mean(white, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Hispanic",
n = sum(!is.na(hispanic_yes)),
proportion = mean(hispanic_yes, na.rm = TRUE),
.groups = "drop"
),
balance_data %>%
group_by(condition_cell) %>%
summarize(
covariate = "Metropolitan",
n = sum(!is.na(metro_yes)),
proportion = mean(metro_yes, na.rm = TRUE),
.groups = "drop"
)
) %>%
arrange(covariate, condition_cell)
kable(
numeric_balance,
digits = 2,
caption = "Covariate balance check for continuous and ordinal pretreatment variables by experimental cell."
)
Covariate balance check for continuous and ordinal pretreatment
variables by experimental cell.
| Chinese strike / U.S. victim | Autonomous AI |
AI comfort |
733 |
0.52 |
1.09 |
| Chinese strike / U.S. victim | Human-operated |
AI comfort |
735 |
0.37 |
1.08 |
| U.S. strike / Chinese victim | Autonomous AI |
AI comfort |
724 |
0.47 |
1.09 |
| U.S. strike / Chinese victim | Human-operated |
AI comfort |
730 |
0.43 |
1.10 |
| Chinese strike / U.S. victim | Autonomous AI |
Age group (ordinal) |
726 |
2.72 |
0.95 |
| Chinese strike / U.S. victim | Human-operated |
Age group (ordinal) |
728 |
2.72 |
0.94 |
| U.S. strike / Chinese victim | Autonomous AI |
Age group (ordinal) |
725 |
2.73 |
0.94 |
| U.S. strike / Chinese victim | Human-operated |
Age group (ordinal) |
725 |
2.70 |
0.95 |
| Chinese strike / U.S. victim | Autonomous AI |
China minus U.S. AI effectiveness |
720 |
-7.38 |
21.80 |
| Chinese strike / U.S. victim | Human-operated |
China minus U.S. AI effectiveness |
722 |
-8.52 |
25.11 |
| U.S. strike / Chinese victim | Autonomous AI |
China minus U.S. AI effectiveness |
716 |
-8.65 |
26.67 |
| U.S. strike / Chinese victim | Human-operated |
China minus U.S. AI effectiveness |
718 |
-6.80 |
24.39 |
| Chinese strike / U.S. victim | Autonomous AI |
Education (ordinal) |
727 |
3.91 |
1.51 |
| Chinese strike / U.S. victim | Human-operated |
Education (ordinal) |
729 |
3.90 |
1.54 |
| U.S. strike / Chinese victim | Autonomous AI |
Education (ordinal) |
725 |
3.89 |
1.52 |
| U.S. strike / Chinese victim | Human-operated |
Education (ordinal) |
725 |
3.98 |
1.48 |
| Chinese strike / U.S. victim | Autonomous AI |
Income (ordinal) |
727 |
3.68 |
1.74 |
| Chinese strike / U.S. victim | Human-operated |
Income (ordinal) |
729 |
3.50 |
1.70 |
| U.S. strike / Chinese victim | Autonomous AI |
Income (ordinal) |
725 |
3.52 |
1.64 |
| U.S. strike / Chinese victim | Human-operated |
Income (ordinal) |
724 |
3.60 |
1.70 |
kable(
binary_balance,
digits = 3,
caption = "Covariate balance check for binary demographic variables by experimental cell."
)
Covariate balance check for binary demographic variables by
experimental cell.
| Chinese strike / U.S. victim | Autonomous AI |
Female |
727 |
0.549 |
| Chinese strike / U.S. victim | Human-operated |
Female |
729 |
0.539 |
| U.S. strike / Chinese victim | Autonomous AI |
Female |
725 |
0.570 |
| U.S. strike / Chinese victim | Human-operated |
Female |
725 |
0.539 |
| Chinese strike / U.S. victim | Autonomous AI |
Hispanic |
727 |
0.122 |
| Chinese strike / U.S. victim | Human-operated |
Hispanic |
729 |
0.132 |
| U.S. strike / Chinese victim | Autonomous AI |
Hispanic |
725 |
0.124 |
| U.S. strike / Chinese victim | Human-operated |
Hispanic |
725 |
0.112 |
| Chinese strike / U.S. victim | Autonomous AI |
Metropolitan |
727 |
0.864 |
| Chinese strike / U.S. victim | Human-operated |
Metropolitan |
728 |
0.889 |
| U.S. strike / Chinese victim | Autonomous AI |
Metropolitan |
725 |
0.884 |
| U.S. strike / Chinese victim | Human-operated |
Metropolitan |
725 |
0.887 |
| Chinese strike / U.S. victim | Autonomous AI |
Republican |
727 |
0.374 |
| Chinese strike / U.S. victim | Human-operated |
Republican |
729 |
0.362 |
| U.S. strike / Chinese victim | Autonomous AI |
Republican |
725 |
0.374 |
| U.S. strike / Chinese victim | Human-operated |
Republican |
725 |
0.370 |
| Chinese strike / U.S. victim | Autonomous AI |
White |
727 |
0.757 |
| Chinese strike / U.S. victim | Human-operated |
White |
729 |
0.734 |
| U.S. strike / Chinese victim | Autonomous AI |
White |
725 |
0.746 |
| U.S. strike / Chinese victim | Human-operated |
White |
725 |
0.757 |
Complete-Case Diagnostics
The primary adjusted model uses complete cases for the outcome,
preregistered covariates, and demographic controls. This section reports
how many respondents are excluded by that requirement and whether the
retained and excluded respondents differ on observed variables. These
diagnostics help contextualize the covariate-adjusted model; they do not
change the preregistered estimand.
complete_case_diagnostics <- prereg_analysis_data %>%
mutate(
primary_model_sample = ifelse(ResponseId %in% prereg_primary_data$ResponseId, "Included", "Dropped"),
republican = pid_republican,
female = gender_female,
white = ifelse(race_white == "White", 1, 0),
hispanic_yes = ifelse(hispanic == "Yes", 1, 0),
metro_yes = ifelse(metro == "Metropolitan", 1, 0)
)
complete_case_counts <- complete_case_diagnostics %>%
count(primary_model_sample) %>%
mutate(percent = n / sum(n))
complete_case_numeric <- bind_rows(
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Perceived intentionality", n = sum(!is.na(perceived_intentionality)), mean = mean(perceived_intentionality, na.rm = TRUE), sd = sd(perceived_intentionality, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "AI comfort", n = sum(!is.na(ai_comfort)), mean = mean(ai_comfort, na.rm = TRUE), sd = sd(ai_comfort, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "China minus U.S. AI effectiveness", n = sum(!is.na(relative_china_us_ai)), mean = mean(relative_china_us_ai, na.rm = TRUE), sd = sd(relative_china_us_ai, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Age group (ordinal)", n = sum(!is.na(age_ordinal)), mean = mean(age_ordinal, na.rm = TRUE), sd = sd(age_ordinal, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Education (ordinal)", n = sum(!is.na(education_ordinal)), mean = mean(education_ordinal, na.rm = TRUE), sd = sd(education_ordinal, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Income (ordinal)", n = sum(!is.na(income_ordinal)), mean = mean(income_ordinal, na.rm = TRUE), sd = sd(income_ordinal, na.rm = TRUE), .groups = "drop")
) %>%
arrange(variable, primary_model_sample)
complete_case_binary <- bind_rows(
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Republican", n = sum(!is.na(republican)), proportion = mean(republican, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Female", n = sum(!is.na(female)), proportion = mean(female, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "White", n = sum(!is.na(white)), proportion = mean(white, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Hispanic", n = sum(!is.na(hispanic_yes)), proportion = mean(hispanic_yes, na.rm = TRUE), .groups = "drop"),
complete_case_diagnostics %>%
group_by(primary_model_sample) %>%
summarize(variable = "Metropolitan", n = sum(!is.na(metro_yes)), proportion = mean(metro_yes, na.rm = TRUE), .groups = "drop")
) %>%
arrange(variable, primary_model_sample)
kable(complete_case_counts, digits = 3, caption = "Respondents included in and dropped from the covariate-complete primary model.")
Respondents included in and dropped from the covariate-complete
primary model.
| Dropped |
102 |
0.035 |
| Included |
2833 |
0.965 |
kable(complete_case_numeric, digits = 2, caption = "Observed differences between included and dropped respondents for numeric variables.")
Observed differences between included and dropped respondents
for numeric variables.
| Dropped |
AI comfort |
89 |
0.17 |
1.19 |
| Included |
AI comfort |
2833 |
0.46 |
1.09 |
| Dropped |
Age group (ordinal) |
71 |
2.75 |
1.02 |
| Included |
Age group (ordinal) |
2833 |
2.71 |
0.94 |
| Dropped |
China minus U.S. AI effectiveness |
43 |
-9.28 |
24.01 |
| Included |
China minus U.S. AI effectiveness |
2833 |
-7.82 |
24.57 |
| Dropped |
Education (ordinal) |
73 |
4.04 |
1.42 |
| Included |
Education (ordinal) |
2833 |
3.92 |
1.51 |
| Dropped |
Income (ordinal) |
72 |
3.58 |
1.75 |
| Included |
Income (ordinal) |
2833 |
3.57 |
1.69 |
| Dropped |
Perceived intentionality |
102 |
60.57 |
28.12 |
| Included |
Perceived intentionality |
2833 |
62.92 |
24.84 |
kable(complete_case_binary, digits = 3, caption = "Observed differences between included and dropped respondents for binary variables.")
Observed differences between included and dropped respondents
for binary variables.
| Dropped |
Female |
73 |
0.507 |
| Included |
Female |
2833 |
0.550 |
| Dropped |
Hispanic |
73 |
0.096 |
| Included |
Hispanic |
2833 |
0.123 |
| Dropped |
Metropolitan |
72 |
0.903 |
| Included |
Metropolitan |
2833 |
0.880 |
| Dropped |
Republican |
73 |
0.301 |
| Included |
Republican |
2833 |
0.372 |
| Dropped |
White |
73 |
0.726 |
| Included |
White |
2833 |
0.749 |
Cell Means for Primary Outcome
prereg_cell_means <- prereg_analysis_data %>%
group_by(country_condition, weapons_condition) %>%
summarize(
n = n(),
mean = mean(perceived_intentionality),
se = sd(perceived_intentionality) / sqrt(n),
ci_low = mean - 1.96 * se,
ci_high = mean + 1.96 * se,
.groups = "drop"
)
kable(
prereg_cell_means,
digits = 2,
caption = "Mean perceived intentionality and 95% confidence intervals by experimental cell."
)
Mean perceived intentionality and 95% confidence intervals by
experimental cell.
| Chinese strike / U.S. victim |
Autonomous AI |
737 |
62.09 |
0.87 |
60.38 |
63.80 |
| Chinese strike / U.S. victim |
Human-operated |
737 |
72.11 |
0.85 |
70.45 |
73.77 |
| U.S. strike / Chinese victim |
Autonomous AI |
728 |
54.21 |
0.94 |
52.37 |
56.06 |
| U.S. strike / Chinese victim |
Human-operated |
733 |
62.83 |
0.91 |
61.06 |
64.61 |
prereg_cell_means_plot_data <- prereg_cell_means %>%
mutate(
country_condition = factor(
country_condition,
levels = c("Chinese strike / U.S. victim", "U.S. strike / Chinese victim"),
labels = c("Chinese strike", "U.S. strike")
),
weapons_condition = factor(
weapons_condition,
levels = c("Human-operated", "Autonomous AI")
)
)
ggplot(
prereg_cell_means_plot_data,
aes(x = weapons_condition, y = mean, color = country_condition, group = country_condition)
) +
geom_line(linewidth = 1, alpha = 0.45) +
geom_point(size = 3.3) +
geom_errorbar(aes(ymin = ci_low, ymax = ci_high), width = 0.08, linewidth = 0.8) +
scale_color_manual(
values = c("Chinese strike" = "#A63A33", "U.S. strike" = "#235A8C"),
name = "Country scenario"
) +
scale_y_continuous(
limits = c(50, 80),
breaks = seq(50, 80, 5)
) +
labs(
title = "Preregistered Cell Means for Perceived Intentionality",
x = "Weapons-system condition",
y = "Perceived intentionality",
caption = "Error bars are 95% confidence intervals."
) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top",
panel.grid.major.x = element_blank()
)

Primary Preregistered Intentionality Model
This model regresses perceived intentionality on the country-scenario
indicator, the autonomous-AI indicator, their interaction, preregistered
covariates, and demographic controls. Continuous covariates are
demeaned. HC2 heteroskedasticity-consistent standard errors are used for
two-sided tests with alpha = .05.
prereg_primary_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
prereg_primary_vcov <- vcovHC(prereg_primary_model, type = "HC2")
prereg_primary_coeftest <- coeftest(prereg_primary_model, vcov. = prereg_primary_vcov)
prereg_primary_ci <- coefci(prereg_primary_model, vcov. = prereg_primary_vcov)
prereg_primary_results <- data.frame(
term = rownames(prereg_primary_coeftest),
estimate = prereg_primary_coeftest[, 1],
hc2_se = prereg_primary_coeftest[, 2],
statistic = prereg_primary_coeftest[, 3],
p_value = prereg_primary_coeftest[, 4],
ci_low = prereg_primary_ci[, 1],
ci_high = prereg_primary_ci[, 2],
row.names = NULL
)
kable(
prereg_primary_results,
digits = 3,
caption = "Primary preregistered OLS model with HC2 standard errors."
)
Primary preregistered OLS model with HC2 standard
errors.
| (Intercept) |
64.156 |
2.451 |
26.180 |
0.000 |
59.351 |
68.962 |
| country_scenario |
9.039 |
1.253 |
7.214 |
0.000 |
6.582 |
11.496 |
| autonomous_ai |
-9.030 |
1.316 |
-6.864 |
0.000 |
-11.609 |
-6.450 |
| ai_comfort_c |
1.284 |
0.455 |
2.825 |
0.005 |
0.393 |
2.176 |
| relative_china_us_ai_c |
0.047 |
0.021 |
2.251 |
0.024 |
0.006 |
0.088 |
| pid_republican |
2.034 |
0.975 |
2.087 |
0.037 |
0.123 |
3.945 |
| age_ordinal |
-0.578 |
0.500 |
-1.155 |
0.248 |
-1.558 |
0.403 |
| gender_female |
0.142 |
0.925 |
0.154 |
0.878 |
-1.672 |
1.956 |
| education_ordinal |
-0.178 |
0.345 |
-0.516 |
0.606 |
-0.854 |
0.498 |
| income_ordinal |
-0.047 |
0.325 |
-0.144 |
0.886 |
-0.683 |
0.590 |
| race_whiteWhite |
-1.212 |
1.091 |
-1.110 |
0.267 |
-3.351 |
0.928 |
| hispanicYes |
2.772 |
1.378 |
2.012 |
0.044 |
0.071 |
5.473 |
| metroMetropolitan |
1.390 |
1.391 |
0.999 |
0.318 |
-1.338 |
4.117 |
| country_scenario:autonomous_ai |
-1.231 |
1.806 |
-0.682 |
0.496 |
-4.773 |
2.311 |
Unadjusted and Adjusted Treatment Estimates
Coding note: the unadjusted model estimates the treatment-cell
differences using only the randomized country-scenario indicator, the
autonomous-AI indicator, and their interaction. The adjusted model is
the preregistered primary model above. Showing them side by side makes
it easier to see whether covariate adjustment changes the substantive
treatment estimates.
prereg_unadjusted_full_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai,
data = prereg_analysis_data
)
prereg_unadjusted_complete_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai,
data = prereg_primary_data
)
prereg_unadjusted_full_vcov <- vcovHC(prereg_unadjusted_full_model, type = "HC2")
prereg_unadjusted_full_coeftest <- coeftest(prereg_unadjusted_full_model, vcov. = prereg_unadjusted_full_vcov)
prereg_unadjusted_full_ci <- coefci(prereg_unadjusted_full_model, vcov. = prereg_unadjusted_full_vcov)
prereg_unadjusted_complete_vcov <- vcovHC(prereg_unadjusted_complete_model, type = "HC2")
prereg_unadjusted_complete_coeftest <- coeftest(prereg_unadjusted_complete_model, vcov. = prereg_unadjusted_complete_vcov)
prereg_unadjusted_complete_ci <- coefci(prereg_unadjusted_complete_model, vcov. = prereg_unadjusted_complete_vcov)
prereg_unadjusted_full_results <- data.frame(
model = "Unadjusted, full outcome sample",
term = rownames(prereg_unadjusted_full_coeftest),
estimate = prereg_unadjusted_full_coeftest[, 1],
hc2_se = prereg_unadjusted_full_coeftest[, 2],
p_value = prereg_unadjusted_full_coeftest[, 4],
ci_low = prereg_unadjusted_full_ci[, 1],
ci_high = prereg_unadjusted_full_ci[, 2],
row.names = NULL
)
prereg_unadjusted_complete_results <- data.frame(
model = "Unadjusted, covariate-complete sample",
term = rownames(prereg_unadjusted_complete_coeftest),
estimate = prereg_unadjusted_complete_coeftest[, 1],
hc2_se = prereg_unadjusted_complete_coeftest[, 2],
p_value = prereg_unadjusted_complete_coeftest[, 4],
ci_low = prereg_unadjusted_complete_ci[, 1],
ci_high = prereg_unadjusted_complete_ci[, 2],
row.names = NULL
)
prereg_adjusted_treatment_results <- prereg_primary_results %>%
mutate(model = "Adjusted, preregistered primary model", .before = term)
unadjusted_adjusted_treatment_terms <- c(
"(Intercept)",
"country_scenario",
"autonomous_ai",
"country_scenario:autonomous_ai"
)
prereg_unadjusted_adjusted_comparison <- bind_rows(
prereg_unadjusted_full_results,
prereg_unadjusted_complete_results,
prereg_adjusted_treatment_results
) %>%
filter(term %in% unadjusted_adjusted_treatment_terms)
kable(
prereg_unadjusted_adjusted_comparison,
digits = 3,
caption = "Unadjusted and adjusted treatment estimates for perceived intentionality. All standard errors are HC2."
)
Unadjusted and adjusted treatment estimates for perceived
intentionality. All standard errors are HC2.
| Unadjusted, full outcome sample |
(Intercept) |
62.834 |
0.906 |
0.000 |
61.058 |
64.609 |
NA |
| Unadjusted, full outcome sample |
country_scenario |
9.276 |
1.240 |
0.000 |
6.845 |
11.708 |
NA |
| Unadjusted, full outcome sample |
autonomous_ai |
-8.622 |
1.306 |
0.000 |
-11.182 |
-6.062 |
NA |
| Unadjusted, full outcome sample |
country_scenario:autonomous_ai |
-1.397 |
1.784 |
0.434 |
-4.894 |
2.100 |
NA |
| Unadjusted, covariate-complete sample |
(Intercept) |
63.218 |
0.918 |
0.000 |
61.417 |
65.019 |
NA |
| Unadjusted, covariate-complete sample |
country_scenario |
8.958 |
1.253 |
0.000 |
6.501 |
11.415 |
NA |
| Unadjusted, covariate-complete sample |
autonomous_ai |
-9.023 |
1.318 |
0.000 |
-11.608 |
-6.439 |
NA |
| Unadjusted, covariate-complete sample |
country_scenario:autonomous_ai |
-1.090 |
1.805 |
0.546 |
-4.629 |
2.449 |
NA |
| Adjusted, preregistered primary model |
(Intercept) |
64.156 |
2.451 |
0.000 |
59.351 |
68.962 |
26.180 |
| Adjusted, preregistered primary model |
country_scenario |
9.039 |
1.253 |
0.000 |
6.582 |
11.496 |
7.214 |
| Adjusted, preregistered primary model |
autonomous_ai |
-9.030 |
1.316 |
0.000 |
-11.609 |
-6.450 |
-6.864 |
| Adjusted, preregistered primary model |
country_scenario:autonomous_ai |
-1.231 |
1.806 |
0.496 |
-4.773 |
2.311 |
-0.682 |
Planned Contrasts for H1-H4
prereg_contrast_weights <- matrix(
0,
nrow = 4,
ncol = length(coef(prereg_primary_model))
)
colnames(prereg_contrast_weights) <- names(coef(prereg_primary_model))
rownames(prereg_contrast_weights) <- c(
"H1: Chinese strike vs. U.S. strike among human-operated systems",
"Autonomous AI effect in U.S.-strike / Chinese-victim condition",
"Autonomous AI effect in Chinese-strike / U.S.-victim condition",
"Country-scenario by autonomous-AI interaction"
)
prereg_contrast_weights["H1: Chinese strike vs. U.S. strike among human-operated systems", "country_scenario"] <- 1
prereg_contrast_weights["Autonomous AI effect in U.S.-strike / Chinese-victim condition", "autonomous_ai"] <- 1
prereg_contrast_weights["Autonomous AI effect in Chinese-strike / U.S.-victim condition", "autonomous_ai"] <- 1
prereg_contrast_weights["Autonomous AI effect in Chinese-strike / U.S.-victim condition", "country_scenario:autonomous_ai"] <- 1
prereg_contrast_weights["Country-scenario by autonomous-AI interaction", "country_scenario:autonomous_ai"] <- 1
prereg_contrast_estimate <- as.numeric(prereg_contrast_weights %*% coef(prereg_primary_model))
prereg_contrast_se <- sqrt(diag(prereg_contrast_weights %*% prereg_primary_vcov %*% t(prereg_contrast_weights)))
prereg_contrast_statistic <- prereg_contrast_estimate / prereg_contrast_se
prereg_contrast_p <- 2 * pt(abs(prereg_contrast_statistic), df = df.residual(prereg_primary_model), lower.tail = FALSE)
prereg_contrast_critical <- qt(0.975, df = df.residual(prereg_primary_model))
prereg_contrasts <- data.frame(
contrast = rownames(prereg_contrast_weights),
estimate = prereg_contrast_estimate,
hc2_se = prereg_contrast_se,
statistic = prereg_contrast_statistic,
p_value = prereg_contrast_p,
ci_low = prereg_contrast_estimate - prereg_contrast_critical * prereg_contrast_se,
ci_high = prereg_contrast_estimate + prereg_contrast_critical * prereg_contrast_se,
row.names = NULL
)
kable(
prereg_contrasts,
digits = 3,
caption = "Planned treatment contrasts using HC2 standard errors."
)
Planned treatment contrasts using HC2 standard
errors.
| H1: Chinese strike vs. U.S. strike among human-operated
systems |
9.039 |
1.253 |
7.214 |
0.000 |
6.582 |
11.496 |
| Autonomous AI effect in U.S.-strike / Chinese-victim
condition |
-9.030 |
1.316 |
-6.864 |
0.000 |
-11.609 |
-6.450 |
| Autonomous AI effect in Chinese-strike / U.S.-victim
condition |
-10.261 |
1.237 |
-8.295 |
0.000 |
-12.686 |
-7.835 |
| Country-scenario by autonomous-AI interaction |
-1.231 |
1.806 |
-0.682 |
0.496 |
-4.773 |
2.311 |
prereg_contrast_plot_data <- prereg_contrasts %>%
mutate(
contrast_label = case_when(
grepl("^H1", contrast) ~ "H1: Chinese vs. U.S. strike\namong human-operated systems",
grepl("U.S.-strike", contrast) ~ "Autonomous effect\nin U.S.-strike condition",
grepl("Chinese-strike", contrast) ~ "Autonomous effect\nin Chinese-strike condition",
TRUE ~ "Country scenario x\nautonomous AI interaction"
),
contrast_label = factor(
contrast_label,
levels = c(
"H1: Chinese vs. U.S. strike\namong human-operated systems",
"Autonomous effect\nin U.S.-strike condition",
"Autonomous effect\nin Chinese-strike condition",
"Country scenario x\nautonomous AI interaction"
)
)
)
ggplot(prereg_contrast_plot_data, aes(x = estimate, y = contrast_label)) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray55") +
geom_errorbarh(aes(xmin = ci_low, xmax = ci_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 3) +
scale_y_discrete(limits = rev(levels(prereg_contrast_plot_data$contrast_label))) +
labs(
title = "Preregistered Treatment Contrasts for Intentionality",
x = "Estimated effect on perceived intentionality",
y = NULL,
caption = "Points are OLS estimates; error bars are 95% CIs using HC2 standard errors."
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank()
)
## Warning: `geom_errobarh()` was deprecated in ggplot2 4.0.0.
## ℹ Please use the `orientation` argument of `geom_errorbar()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `height` was translated to `width`.

Weighted Primary Model
Coding note: this is a robustness check using the appended respondent
weight. It keeps the same outcome, treatment indicators, interaction,
preregistered covariates, and demographic controls as the primary model.
The unweighted covariate-adjusted model remains the primary
preregistered analysis unless the preregistration explicitly says
weights are primary.
prereg_weighted_data <- prereg_primary_data %>%
filter(!is.na(survey_weight),
survey_weight > 0)
prereg_weighted_primary_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_weighted_data,
weights = survey_weight
)
prereg_weighted_primary_vcov <- vcovHC(prereg_weighted_primary_model, type = "HC2")
prereg_weighted_primary_coeftest <- coeftest(prereg_weighted_primary_model, vcov. = prereg_weighted_primary_vcov)
prereg_weighted_primary_ci <- coefci(prereg_weighted_primary_model, vcov. = prereg_weighted_primary_vcov)
prereg_weighted_primary_results <- data.frame(
term = rownames(prereg_weighted_primary_coeftest),
estimate = prereg_weighted_primary_coeftest[, 1],
hc2_se = prereg_weighted_primary_coeftest[, 2],
statistic = prereg_weighted_primary_coeftest[, 3],
p_value = prereg_weighted_primary_coeftest[, 4],
ci_low = prereg_weighted_primary_ci[, 1],
ci_high = prereg_weighted_primary_ci[, 2],
row.names = NULL
)
kable(
prereg_weighted_primary_results,
digits = 3,
caption = paste0("Weighted version of the primary preregistered model using HC2 standard errors (N = ", nrow(prereg_weighted_data), ").")
)
Weighted version of the primary preregistered model using HC2
standard errors (N = 2833).
| (Intercept) |
60.343 |
2.962 |
20.375 |
0.000 |
54.536 |
66.150 |
| country_scenario |
8.639 |
1.527 |
5.658 |
0.000 |
5.645 |
11.633 |
| autonomous_ai |
-9.394 |
1.638 |
-5.735 |
0.000 |
-12.606 |
-6.182 |
| ai_comfort_c |
1.278 |
0.570 |
2.244 |
0.025 |
0.161 |
2.395 |
| relative_china_us_ai_c |
0.029 |
0.024 |
1.187 |
0.235 |
-0.019 |
0.077 |
| pid_republican |
1.869 |
1.186 |
1.575 |
0.115 |
-0.457 |
4.195 |
| age_ordinal |
0.131 |
0.590 |
0.223 |
0.824 |
-1.025 |
1.288 |
| gender_female |
-0.282 |
1.143 |
-0.247 |
0.805 |
-2.524 |
1.960 |
| education_ordinal |
-0.141 |
0.433 |
-0.326 |
0.744 |
-0.991 |
0.708 |
| income_ordinal |
0.064 |
0.428 |
0.149 |
0.882 |
-0.775 |
0.903 |
| race_whiteWhite |
-2.445 |
1.386 |
-1.764 |
0.078 |
-5.162 |
0.273 |
| hispanicYes |
3.827 |
1.551 |
2.467 |
0.014 |
0.786 |
6.869 |
| metroMetropolitan |
3.462 |
1.715 |
2.019 |
0.044 |
0.100 |
6.824 |
| country_scenario:autonomous_ai |
0.460 |
2.238 |
0.206 |
0.837 |
-3.928 |
4.848 |
Alternative Demographic Coding Robustness Check
The primary model treats age, education, and income as ordinal
controls. This robustness check treats those variables as categorical
factors instead. The purpose is to check whether the treatment estimates
depend on the linearity assumption implied by ordinal coding.
prereg_categorical_demographics_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_group4 + gender_female + education + income +
race_white + hispanic + metro,
data = prereg_primary_data
)
prereg_categorical_demographics_vcov <- vcovHC(prereg_categorical_demographics_model, type = "HC2")
prereg_categorical_demographics_coeftest <- coeftest(prereg_categorical_demographics_model, vcov. = prereg_categorical_demographics_vcov)
prereg_categorical_demographics_ci <- coefci(prereg_categorical_demographics_model, vcov. = prereg_categorical_demographics_vcov)
prereg_categorical_demographics_results <- data.frame(
term = rownames(prereg_categorical_demographics_coeftest),
estimate = prereg_categorical_demographics_coeftest[, 1],
hc2_se = prereg_categorical_demographics_coeftest[, 2],
statistic = prereg_categorical_demographics_coeftest[, 3],
p_value = prereg_categorical_demographics_coeftest[, 4],
ci_low = prereg_categorical_demographics_ci[, 1],
ci_high = prereg_categorical_demographics_ci[, 2],
row.names = NULL
)
prereg_categorical_demographics_treatment_results <- prereg_categorical_demographics_results %>%
filter(term %in% c("country_scenario", "autonomous_ai", "country_scenario:autonomous_ai"))
kable(
prereg_categorical_demographics_treatment_results,
digits = 3,
caption = "Treatment coefficients from the robustness model with age, education, and income entered as categorical controls."
)
Treatment coefficients from the robustness model with age,
education, and income entered as categorical controls.
| country_scenario |
9.007 |
1.254 |
7.183 |
0.000 |
6.548 |
11.466 |
| autonomous_ai |
-9.066 |
1.314 |
-6.897 |
0.000 |
-11.644 |
-6.489 |
| country_scenario:autonomous_ai |
-1.221 |
1.806 |
-0.676 |
0.499 |
-4.762 |
2.319 |
Treatment-Estimate Robustness Summary
This table gathers the focal treatment coefficients across the main
specification checks above. It is intended as a compact audit of whether
the main treatment pattern changes across unadjusted, adjusted,
weighted, and categorical-demographic specifications.
treatment_robustness_results <- bind_rows(
prereg_unadjusted_full_results %>%
mutate(specification = "Unadjusted, full outcome sample", .before = term),
prereg_unadjusted_complete_results %>%
mutate(specification = "Unadjusted, covariate-complete sample", .before = term),
prereg_primary_results %>%
mutate(specification = "Adjusted primary model", .before = term),
prereg_weighted_primary_results %>%
mutate(specification = "Weighted adjusted primary model", .before = term),
prereg_categorical_demographics_results %>%
mutate(specification = "Adjusted model with categorical demographics", .before = term)
) %>%
filter(term %in% c("country_scenario", "autonomous_ai", "country_scenario:autonomous_ai")) %>%
mutate(
term_label = case_when(
term == "country_scenario" ~ "Chinese vs. U.S. strike among human-operated systems",
term == "autonomous_ai" ~ "Autonomous effect in U.S.-strike condition",
TRUE ~ "Country scenario x autonomous AI interaction"
)
) %>%
select(specification, term_label, estimate, hc2_se, p_value, ci_low, ci_high)
kable(
treatment_robustness_results,
digits = 3,
caption = "Focal treatment coefficients across primary and robustness specifications."
)
Focal treatment coefficients across primary and robustness
specifications.
| Unadjusted, full outcome sample |
Chinese vs. U.S. strike among human-operated
systems |
9.276 |
1.240 |
0.000 |
6.845 |
11.708 |
| Unadjusted, full outcome sample |
Autonomous effect in U.S.-strike condition |
-8.622 |
1.306 |
0.000 |
-11.182 |
-6.062 |
| Unadjusted, full outcome sample |
Country scenario x autonomous AI interaction |
-1.397 |
1.784 |
0.434 |
-4.894 |
2.100 |
| Unadjusted, covariate-complete sample |
Chinese vs. U.S. strike among human-operated
systems |
8.958 |
1.253 |
0.000 |
6.501 |
11.415 |
| Unadjusted, covariate-complete sample |
Autonomous effect in U.S.-strike condition |
-9.023 |
1.318 |
0.000 |
-11.608 |
-6.439 |
| Unadjusted, covariate-complete sample |
Country scenario x autonomous AI interaction |
-1.090 |
1.805 |
0.546 |
-4.629 |
2.449 |
| Adjusted primary model |
Chinese vs. U.S. strike among human-operated
systems |
9.039 |
1.253 |
0.000 |
6.582 |
11.496 |
| Adjusted primary model |
Autonomous effect in U.S.-strike condition |
-9.030 |
1.316 |
0.000 |
-11.609 |
-6.450 |
| Adjusted primary model |
Country scenario x autonomous AI interaction |
-1.231 |
1.806 |
0.496 |
-4.773 |
2.311 |
| Weighted adjusted primary model |
Chinese vs. U.S. strike among human-operated
systems |
8.639 |
1.527 |
0.000 |
5.645 |
11.633 |
| Weighted adjusted primary model |
Autonomous effect in U.S.-strike condition |
-9.394 |
1.638 |
0.000 |
-12.606 |
-6.182 |
| Weighted adjusted primary model |
Country scenario x autonomous AI interaction |
0.460 |
2.238 |
0.837 |
-3.928 |
4.848 |
| Adjusted model with categorical demographics |
Chinese vs. U.S. strike among human-operated
systems |
9.007 |
1.254 |
0.000 |
6.548 |
11.466 |
| Adjusted model with categorical demographics |
Autonomous effect in U.S.-strike condition |
-9.066 |
1.314 |
0.000 |
-11.644 |
-6.489 |
| Adjusted model with categorical demographics |
Country scenario x autonomous AI interaction |
-1.221 |
1.806 |
0.499 |
-4.762 |
2.319 |
Equivalence-Style Tests for Negligible Effects
For the preregistered equivalence-style tests, a meaningful effect is
defined as Cohen’s D = .20. The table converts that threshold into raw
intentionality points using the standard deviation of the primary model
sample. These tests are useful when the autonomous-AI coefficients are
small: instead of only asking whether an effect is statistically
distinguishable from zero, they ask whether the estimate is
statistically contained inside the preregistered negligible-effect
range.
sesoi_intentionality <- 0.20 * sd(prereg_primary_data$perceived_intentionality, na.rm = TRUE)
prereg_equivalence_weights <- prereg_contrast_weights[
c(
"Autonomous AI effect in U.S.-strike / Chinese-victim condition",
"Autonomous AI effect in Chinese-strike / U.S.-victim condition"
),
,
drop = FALSE
]
prereg_equivalence_estimate <- as.numeric(prereg_equivalence_weights %*% coef(prereg_primary_model))
prereg_equivalence_se <- sqrt(diag(prereg_equivalence_weights %*% prereg_primary_vcov %*% t(prereg_equivalence_weights)))
prereg_equivalence_p_lower <- pt(
(prereg_equivalence_estimate - (-sesoi_intentionality)) / prereg_equivalence_se,
df = df.residual(prereg_primary_model),
lower.tail = FALSE
)
prereg_equivalence_p_upper <- pt(
(prereg_equivalence_estimate - sesoi_intentionality) / prereg_equivalence_se,
df = df.residual(prereg_primary_model),
lower.tail = TRUE
)
prereg_equivalence_tests <- data.frame(
contrast = rownames(prereg_equivalence_weights),
estimate = prereg_equivalence_estimate,
lower_bound = -sesoi_intentionality,
upper_bound = sesoi_intentionality,
hc2_se = prereg_equivalence_se,
p_lower = prereg_equivalence_p_lower,
p_upper = prereg_equivalence_p_upper,
p_tost = pmax(prereg_equivalence_p_lower, prereg_equivalence_p_upper),
equivalent_at_alpha_05 = pmax(prereg_equivalence_p_lower, prereg_equivalence_p_upper) < 0.05,
row.names = NULL
)
kable(
prereg_equivalence_tests,
digits = 3,
caption = paste0("Equivalence-style tests using +/- ", round(sesoi_intentionality, 2), " intentionality points as the meaningful-effect threshold.")
)
Equivalence-style tests using +/- 4.97 intentionality points as
the meaningful-effect threshold.
| Autonomous AI effect in U.S.-strike / Chinese-victim
condition |
-9.030 |
-4.967 |
4.967 |
1.316 |
0.999 |
0 |
0.999 |
FALSE |
| Autonomous AI effect in Chinese-strike / U.S.-victim
condition |
-10.261 |
-4.967 |
4.967 |
1.237 |
1.000 |
0 |
1.000 |
FALSE |
equivalence_critical <- qt(0.95, df = df.residual(prereg_primary_model))
prereg_equivalence_plot_data <- prereg_equivalence_tests %>%
mutate(
ci90_low = estimate - equivalence_critical * hc2_se,
ci90_high = estimate + equivalence_critical * hc2_se,
contrast_label = case_when(
grepl("U.S.-strike", contrast) ~ "Autonomous effect\nin U.S.-strike condition",
TRUE ~ "Autonomous effect\nin Chinese-strike condition"
),
contrast_label = factor(
contrast_label,
levels = c(
"Autonomous effect\nin U.S.-strike condition",
"Autonomous effect\nin Chinese-strike condition"
)
)
)
ggplot(prereg_equivalence_plot_data, aes(x = estimate, y = contrast_label)) +
annotate(
"rect",
xmin = -sesoi_intentionality,
xmax = sesoi_intentionality,
ymin = -Inf,
ymax = Inf,
alpha = 0.12,
fill = "gray60"
) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray50") +
geom_vline(xintercept = c(-sesoi_intentionality, sesoi_intentionality),
linewidth = 0.6,
linetype = "dashed",
color = "gray40") +
geom_errorbarh(aes(xmin = ci90_low, xmax = ci90_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 3) +
scale_y_discrete(limits = rev(levels(prereg_equivalence_plot_data$contrast_label))) +
labs(
title = "Equivalence Tests for Negligible Autonomous-AI Effects",
x = "Estimated autonomous-AI effect on perceived intentionality",
y = NULL,
caption = paste0("Shaded area is the preregistered negligible-effect region (+/- ", round(sesoi_intentionality, 2), " points). Error bars are 90% CIs for TOST.")
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank()
)
## `height` was translated to `width`.

Manipulation Check Descriptives
The current Qualtrics export contains manipulation checks for the
country whose weapons system launched the missiles and whether the
system was autonomous or human-operated. It does not contain a separate
victim-country manipulation check.
manipulation_check_overall <- prereg_analysis_data %>%
summarize(
n = n(),
country_check_response_n = sum(!is.na(comp_country_correct)),
country_check_correct = mean(comp_country_correct, na.rm = TRUE),
autonomy_check_response_n = sum(!is.na(comp_autonomy_correct)),
autonomy_check_correct = mean(comp_autonomy_correct, na.rm = TRUE),
both_checks_correct = mean(comp_both_correct, na.rm = TRUE)
)
manipulation_check_by_condition <- prereg_analysis_data %>%
group_by(country_condition, weapons_condition) %>%
summarize(
n = n(),
country_check_correct = mean(comp_country_correct, na.rm = TRUE),
autonomy_check_correct = mean(comp_autonomy_correct, na.rm = TRUE),
both_checks_correct = mean(comp_both_correct, na.rm = TRUE),
.groups = "drop"
)
kable(manipulation_check_overall, digits = 3, caption = "Overall manipulation-check pass rates.")
Overall manipulation-check pass rates.
| 2935 |
2905 |
0.738 |
2935 |
0.808 |
0.66 |
kable(manipulation_check_by_condition, digits = 3, caption = "Manipulation-check pass rates by condition.")
Manipulation-check pass rates by condition.
| Chinese strike / U.S. victim |
Autonomous AI |
737 |
0.800 |
0.821 |
0.722 |
| Chinese strike / U.S. victim |
Human-operated |
737 |
0.749 |
0.775 |
0.644 |
| U.S. strike / Chinese victim |
Autonomous AI |
728 |
0.693 |
0.834 |
0.638 |
| U.S. strike / Chinese victim |
Human-operated |
733 |
0.709 |
0.802 |
0.634 |
Exploratory Model Among Manipulation-Check Passers
prereg_pass_data <- prereg_primary_data %>%
filter(comp_both_correct)
prereg_pass_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_pass_data
)
prereg_pass_vcov <- vcovHC(prereg_pass_model, type = "HC2")
prereg_pass_coeftest <- coeftest(prereg_pass_model, vcov. = prereg_pass_vcov)
prereg_pass_ci <- coefci(prereg_pass_model, vcov. = prereg_pass_vcov)
prereg_pass_results <- data.frame(
term = rownames(prereg_pass_coeftest),
estimate = prereg_pass_coeftest[, 1],
hc2_se = prereg_pass_coeftest[, 2],
statistic = prereg_pass_coeftest[, 3],
p_value = prereg_pass_coeftest[, 4],
ci_low = prereg_pass_ci[, 1],
ci_high = prereg_pass_ci[, 2],
row.names = NULL
)
kable(
prereg_pass_results,
digits = 3,
caption = paste0("Exploratory primary model among manipulation-check passers only (N = ", nrow(prereg_pass_data), ").")
)
Exploratory primary model among manipulation-check passers only
(N = 1880).
| (Intercept) |
70.515 |
3.189 |
22.113 |
0.000 |
64.261 |
76.769 |
| country_scenario |
11.415 |
1.555 |
7.339 |
0.000 |
8.365 |
14.466 |
| autonomous_ai |
-12.483 |
1.725 |
-7.235 |
0.000 |
-15.867 |
-9.100 |
| ai_comfort_c |
1.322 |
0.572 |
2.311 |
0.021 |
0.200 |
2.444 |
| relative_china_us_ai_c |
0.043 |
0.029 |
1.483 |
0.138 |
-0.014 |
0.099 |
| pid_republican |
1.735 |
1.195 |
1.452 |
0.147 |
-0.609 |
4.080 |
| age_ordinal |
-1.031 |
0.617 |
-1.671 |
0.095 |
-2.242 |
0.179 |
| gender_female |
-0.357 |
1.134 |
-0.315 |
0.753 |
-2.581 |
1.868 |
| education_ordinal |
-0.780 |
0.436 |
-1.788 |
0.074 |
-1.635 |
0.075 |
| income_ordinal |
-0.237 |
0.394 |
-0.602 |
0.548 |
-1.009 |
0.535 |
| race_whiteWhite |
-0.797 |
1.416 |
-0.563 |
0.573 |
-3.574 |
1.980 |
| hispanicYes |
3.558 |
1.800 |
1.977 |
0.048 |
0.028 |
7.089 |
| metroMetropolitan |
0.848 |
1.776 |
0.478 |
0.633 |
-2.635 |
4.331 |
| country_scenario:autonomous_ai |
-0.860 |
2.263 |
-0.380 |
0.704 |
-5.299 |
3.579 |
Secondary Outcome Models
The preregistration lists escalation likelihood, escalation
justifiability, and responsibility attributions as exploratory dependent
variables. The following models use the same treatment specification and
preregistered covariates as the primary model.
Likelihood of Escalation
prereg_escalation_likelihood_data <- prereg_primary_data %>%
filter(!is.na(escalation_likelihood))
prereg_escalation_likelihood_model <- lm(
escalation_likelihood ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_escalation_likelihood_data
)
prereg_escalation_likelihood_vcov <- vcovHC(prereg_escalation_likelihood_model, type = "HC2")
prereg_escalation_likelihood_coeftest <- coeftest(prereg_escalation_likelihood_model, vcov. = prereg_escalation_likelihood_vcov)
prereg_escalation_likelihood_ci <- coefci(prereg_escalation_likelihood_model, vcov. = prereg_escalation_likelihood_vcov)
prereg_escalation_likelihood_results <- data.frame(
term = rownames(prereg_escalation_likelihood_coeftest),
estimate = prereg_escalation_likelihood_coeftest[, 1],
hc2_se = prereg_escalation_likelihood_coeftest[, 2],
statistic = prereg_escalation_likelihood_coeftest[, 3],
p_value = prereg_escalation_likelihood_coeftest[, 4],
ci_low = prereg_escalation_likelihood_ci[, 1],
ci_high = prereg_escalation_likelihood_ci[, 2],
row.names = NULL
)
kable(
prereg_escalation_likelihood_results,
digits = 3,
caption = "Likelihood of escalation model with HC2 standard errors."
)
Likelihood of escalation model with HC2 standard
errors.
| (Intercept) |
65.757 |
2.232 |
29.464 |
0.000 |
61.381 |
70.133 |
| country_scenario |
1.081 |
1.137 |
0.950 |
0.342 |
-1.149 |
3.310 |
| autonomous_ai |
0.741 |
1.099 |
0.674 |
0.500 |
-1.415 |
2.897 |
| ai_comfort_c |
0.593 |
0.412 |
1.442 |
0.149 |
-0.214 |
1.400 |
| relative_china_us_ai_c |
0.006 |
0.020 |
0.327 |
0.744 |
-0.032 |
0.045 |
| pid_republican |
-0.556 |
0.878 |
-0.633 |
0.527 |
-2.278 |
1.167 |
| age_ordinal |
-0.673 |
0.447 |
-1.507 |
0.132 |
-1.549 |
0.203 |
| gender_female |
-0.909 |
0.847 |
-1.074 |
0.283 |
-2.570 |
0.751 |
| education_ordinal |
0.005 |
0.320 |
0.017 |
0.986 |
-0.622 |
0.633 |
| income_ordinal |
0.179 |
0.282 |
0.634 |
0.526 |
-0.374 |
0.731 |
| race_whiteWhite |
-1.035 |
1.026 |
-1.008 |
0.313 |
-3.047 |
0.977 |
| hispanicYes |
-2.217 |
1.385 |
-1.600 |
0.110 |
-4.933 |
0.500 |
| metroMetropolitan |
0.510 |
1.281 |
0.399 |
0.690 |
-2.001 |
3.022 |
| country_scenario:autonomous_ai |
-1.644 |
1.636 |
-1.005 |
0.315 |
-4.852 |
1.563 |
Justifiability of Escalation
prereg_escalation_justifiability_data <- prereg_primary_data %>%
filter(!is.na(escalation_justifiability))
prereg_escalation_justifiability_model <- lm(
escalation_justifiability ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_escalation_justifiability_data
)
prereg_escalation_justifiability_vcov <- vcovHC(prereg_escalation_justifiability_model, type = "HC2")
prereg_escalation_justifiability_coeftest <- coeftest(prereg_escalation_justifiability_model, vcov. = prereg_escalation_justifiability_vcov)
prereg_escalation_justifiability_ci <- coefci(prereg_escalation_justifiability_model, vcov. = prereg_escalation_justifiability_vcov)
prereg_escalation_justifiability_results <- data.frame(
term = rownames(prereg_escalation_justifiability_coeftest),
estimate = prereg_escalation_justifiability_coeftest[, 1],
hc2_se = prereg_escalation_justifiability_coeftest[, 2],
statistic = prereg_escalation_justifiability_coeftest[, 3],
p_value = prereg_escalation_justifiability_coeftest[, 4],
ci_low = prereg_escalation_justifiability_ci[, 1],
ci_high = prereg_escalation_justifiability_ci[, 2],
row.names = NULL
)
kable(
prereg_escalation_justifiability_results,
digits = 3,
caption = "Justifiability of escalation model with HC2 standard errors."
)
Justifiability of escalation model with HC2 standard
errors.
| (Intercept) |
60.008 |
2.545 |
23.581 |
0.000 |
55.018 |
64.998 |
| country_scenario |
2.338 |
1.324 |
1.765 |
0.078 |
-0.259 |
4.934 |
| autonomous_ai |
-2.403 |
1.316 |
-1.827 |
0.068 |
-4.983 |
0.177 |
| ai_comfort_c |
1.684 |
0.492 |
3.425 |
0.001 |
0.720 |
2.649 |
| relative_china_us_ai_c |
0.012 |
0.023 |
0.520 |
0.603 |
-0.033 |
0.057 |
| pid_republican |
4.471 |
1.029 |
4.344 |
0.000 |
2.453 |
6.489 |
| age_ordinal |
0.234 |
0.529 |
0.443 |
0.658 |
-0.803 |
1.271 |
| gender_female |
-2.942 |
0.981 |
-2.998 |
0.003 |
-4.866 |
-1.018 |
| education_ordinal |
0.172 |
0.369 |
0.466 |
0.641 |
-0.551 |
0.895 |
| income_ordinal |
-0.045 |
0.329 |
-0.136 |
0.892 |
-0.689 |
0.600 |
| race_whiteWhite |
-2.575 |
1.123 |
-2.293 |
0.022 |
-4.776 |
-0.373 |
| hispanicYes |
1.205 |
1.460 |
0.825 |
0.410 |
-1.659 |
4.068 |
| metroMetropolitan |
1.977 |
1.515 |
1.305 |
0.192 |
-0.993 |
4.947 |
| country_scenario:autonomous_ai |
1.375 |
1.900 |
0.724 |
0.469 |
-2.350 |
5.100 |
prereg_secondary_treatment_results <- bind_rows(
prereg_escalation_likelihood_results %>%
filter(term %in% c("country_scenario", "autonomous_ai", "country_scenario:autonomous_ai")) %>%
mutate(outcome = "Likelihood of escalation", .before = term),
prereg_escalation_justifiability_results %>%
filter(term %in% c("country_scenario", "autonomous_ai", "country_scenario:autonomous_ai")) %>%
mutate(outcome = "Justifiability of escalation", .before = term)
) %>%
mutate(
term_label = case_when(
term == "country_scenario" ~ "Chinese vs. U.S. strike\namong human-operated systems",
term == "autonomous_ai" ~ "Autonomous effect\nin U.S.-strike condition",
TRUE ~ "Country scenario x\nautonomous AI interaction"
)
)
prereg_secondary_treatment_results$term_label <- factor(
prereg_secondary_treatment_results$term_label,
levels = c(
"Chinese vs. U.S. strike\namong human-operated systems",
"Autonomous effect\nin U.S.-strike condition",
"Country scenario x\nautonomous AI interaction"
)
)
ggplot(prereg_secondary_treatment_results, aes(x = estimate, y = term_label)) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray55") +
geom_errorbarh(aes(xmin = ci_low, xmax = ci_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 2.8) +
facet_wrap(~ outcome) +
scale_y_discrete(limits = rev(levels(prereg_secondary_treatment_results$term_label))) +
labs(
title = "Treatment Coefficients for Secondary Outcomes",
x = "Estimated effect",
y = NULL,
caption = "Points are OLS estimates; error bars are 95% CIs using HC2 standard errors."
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank(),
strip.text = element_text(face = "bold")
)
## `height` was translated to `width`.

prereg_responsibility_data <- bind_rows(
prereg_primary_data %>%
transmute(country_scenario, autonomous_ai, ai_comfort_c, relative_china_us_ai_c, pid_republican,
age_ordinal, gender_female, education_ordinal, income_ordinal, race_white, hispanic, metro,
actor = "Senior political leaders", responsibility = as.numeric(resp_leader)),
prereg_primary_data %>%
transmute(country_scenario, autonomous_ai, ai_comfort_c, relative_china_us_ai_c, pid_republican,
age_ordinal, gender_female, education_ordinal, income_ordinal, race_white, hispanic, metro,
actor = "Military officials", responsibility = as.numeric(resp_military)),
prereg_primary_data %>%
transmute(country_scenario, autonomous_ai, ai_comfort_c, relative_china_us_ai_c, pid_republican,
age_ordinal, gender_female, education_ordinal, income_ordinal, race_white, hispanic, metro,
actor = "Human operator", responsibility = as.numeric(resp_pilot)),
prereg_primary_data %>%
transmute(country_scenario, autonomous_ai, ai_comfort_c, relative_china_us_ai_c, pid_republican,
age_ordinal, gender_female, education_ordinal, income_ordinal, race_white, hispanic, metro,
actor = "AI weapons system", responsibility = as.numeric(resp_ai))
) %>%
filter(!is.na(responsibility))
responsibility_treatment_terms <- c(
"country_scenario",
"autonomous_ai",
"country_scenario:autonomous_ai"
)
Responsibility: Senior Political Leaders
prereg_senior_political_leaders_data <- prereg_responsibility_data %>%
filter(actor == "Senior political leaders")
prereg_senior_political_leaders_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_senior_political_leaders_data
)
prereg_senior_political_leaders_vcov <- vcovHC(prereg_senior_political_leaders_model, type = "HC2")
prereg_senior_political_leaders_coeftest <- coeftest(prereg_senior_political_leaders_model, vcov. = prereg_senior_political_leaders_vcov)
prereg_senior_political_leaders_ci <- coefci(prereg_senior_political_leaders_model, vcov. = prereg_senior_political_leaders_vcov)
prereg_senior_political_leaders_results <- data.frame(
term = rownames(prereg_senior_political_leaders_coeftest),
estimate = prereg_senior_political_leaders_coeftest[, 1],
hc2_se = prereg_senior_political_leaders_coeftest[, 2],
statistic = prereg_senior_political_leaders_coeftest[, 3],
p_value = prereg_senior_political_leaders_coeftest[, 4],
ci_low = prereg_senior_political_leaders_ci[, 1],
ci_high = prereg_senior_political_leaders_ci[, 2],
row.names = NULL
)
prereg_senior_political_leaders_treatment_results <- prereg_senior_political_leaders_results %>%
filter(term %in% responsibility_treatment_terms) %>%
mutate(actor = "Senior political leaders", .before = term)
kable(
prereg_senior_political_leaders_treatment_results,
digits = 3,
caption = "Treatment coefficients for responsibility attributed to senior political leaders."
)
Treatment coefficients for responsibility attributed to senior
political leaders.
| Senior political leaders |
country_scenario |
4.968 |
1.306 |
3.804 |
0.000 |
2.407 |
7.529 |
| Senior political leaders |
autonomous_ai |
1.514 |
1.355 |
1.117 |
0.264 |
-1.144 |
4.171 |
| Senior political leaders |
country_scenario:autonomous_ai |
-1.419 |
1.862 |
-0.762 |
0.446 |
-5.070 |
2.232 |
Responsibility: Military Officials
prereg_military_officials_data <- prereg_responsibility_data %>%
filter(actor == "Military officials")
prereg_military_officials_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_military_officials_data
)
prereg_military_officials_vcov <- vcovHC(prereg_military_officials_model, type = "HC2")
prereg_military_officials_coeftest <- coeftest(prereg_military_officials_model, vcov. = prereg_military_officials_vcov)
prereg_military_officials_ci <- coefci(prereg_military_officials_model, vcov. = prereg_military_officials_vcov)
prereg_military_officials_results <- data.frame(
term = rownames(prereg_military_officials_coeftest),
estimate = prereg_military_officials_coeftest[, 1],
hc2_se = prereg_military_officials_coeftest[, 2],
statistic = prereg_military_officials_coeftest[, 3],
p_value = prereg_military_officials_coeftest[, 4],
ci_low = prereg_military_officials_ci[, 1],
ci_high = prereg_military_officials_ci[, 2],
row.names = NULL
)
prereg_military_officials_treatment_results <- prereg_military_officials_results %>%
filter(term %in% responsibility_treatment_terms) %>%
mutate(actor = "Military officials", .before = term)
kable(
prereg_military_officials_treatment_results,
digits = 3,
caption = "Treatment coefficients for responsibility attributed to military officials."
)
Treatment coefficients for responsibility attributed to
military officials.
| Military officials |
country_scenario |
0.801 |
1.209 |
0.663 |
0.507 |
-1.569 |
3.171 |
| Military officials |
autonomous_ai |
0.462 |
1.221 |
0.378 |
0.705 |
-1.933 |
2.856 |
| Military officials |
country_scenario:autonomous_ai |
0.550 |
1.725 |
0.319 |
0.750 |
-2.833 |
3.933 |
Responsibility: Human Operator
prereg_human_operator_data <- prereg_responsibility_data %>%
filter(actor == "Human operator")
prereg_human_operator_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_human_operator_data
)
prereg_human_operator_vcov <- vcovHC(prereg_human_operator_model, type = "HC2")
prereg_human_operator_coeftest <- coeftest(prereg_human_operator_model, vcov. = prereg_human_operator_vcov)
prereg_human_operator_ci <- coefci(prereg_human_operator_model, vcov. = prereg_human_operator_vcov)
prereg_human_operator_results <- data.frame(
term = rownames(prereg_human_operator_coeftest),
estimate = prereg_human_operator_coeftest[, 1],
hc2_se = prereg_human_operator_coeftest[, 2],
statistic = prereg_human_operator_coeftest[, 3],
p_value = prereg_human_operator_coeftest[, 4],
ci_low = prereg_human_operator_ci[, 1],
ci_high = prereg_human_operator_ci[, 2],
row.names = NULL
)
prereg_human_operator_treatment_results <- prereg_human_operator_results %>%
filter(term %in% responsibility_treatment_terms) %>%
mutate(actor = "Human operator", .before = term)
kable(
prereg_human_operator_treatment_results,
digits = 3,
caption = "Treatment coefficients for responsibility attributed to the human operator."
)
Treatment coefficients for responsibility attributed to the
human operator.
| Human operator |
country_scenario |
1.68 |
1.416 |
1.186 |
0.236 |
-1.098 |
4.458 |
Responsibility: AI Weapons System
prereg_ai_weapons_system_data <- prereg_responsibility_data %>%
filter(actor == "AI weapons system")
prereg_ai_weapons_system_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_ai_weapons_system_data
)
prereg_ai_weapons_system_vcov <- vcovHC(prereg_ai_weapons_system_model, type = "HC2")
prereg_ai_weapons_system_coeftest <- coeftest(prereg_ai_weapons_system_model, vcov. = prereg_ai_weapons_system_vcov)
prereg_ai_weapons_system_ci <- coefci(prereg_ai_weapons_system_model, vcov. = prereg_ai_weapons_system_vcov)
prereg_ai_weapons_system_results <- data.frame(
term = rownames(prereg_ai_weapons_system_coeftest),
estimate = prereg_ai_weapons_system_coeftest[, 1],
hc2_se = prereg_ai_weapons_system_coeftest[, 2],
statistic = prereg_ai_weapons_system_coeftest[, 3],
p_value = prereg_ai_weapons_system_coeftest[, 4],
ci_low = prereg_ai_weapons_system_ci[, 1],
ci_high = prereg_ai_weapons_system_ci[, 2],
row.names = NULL
)
prereg_ai_weapons_system_treatment_results <- prereg_ai_weapons_system_results %>%
filter(term %in% responsibility_treatment_terms) %>%
mutate(actor = "AI weapons system", .before = term)
kable(
prereg_ai_weapons_system_treatment_results,
digits = 3,
caption = "Treatment coefficients for responsibility attributed to the AI weapons system."
)
Treatment coefficients for responsibility attributed to the AI
weapons system.
| AI weapons system |
country_scenario |
-1.339 |
1.66 |
-0.807 |
0.42 |
-4.595 |
1.917 |
prereg_responsibility_treatment_results <- bind_rows(
prereg_senior_political_leaders_treatment_results,
prereg_military_officials_treatment_results,
prereg_human_operator_treatment_results,
prereg_ai_weapons_system_treatment_results
) %>%
mutate(
term_label = case_when(
term == "country_scenario" ~ "Chinese vs. U.S. strike",
term == "autonomous_ai" ~ "Autonomous vs. human",
TRUE ~ "Interaction"
)
)
prereg_responsibility_treatment_results$term_label <- factor(
prereg_responsibility_treatment_results$term_label,
levels = c("Chinese vs. U.S. strike", "Autonomous vs. human", "Interaction")
)
ggplot(prereg_responsibility_treatment_results, aes(x = estimate, y = term_label)) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray55") +
geom_errorbarh(aes(xmin = ci_low, xmax = ci_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 2.8) +
facet_wrap(~ actor, ncol = 2) +
scale_y_discrete(limits = rev(levels(prereg_responsibility_treatment_results$term_label))) +
labs(
title = "Treatment Coefficients for Responsibility Attributions",
x = "Estimated effect on perceived responsibility",
y = NULL,
caption = "Error bars are 95% CIs using HC2 standard errors. Human-operator and AI-system responsibility were only asked in their corresponding weapons-system conditions."
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank(),
strip.text = element_text(face = "bold")
)
## `height` was translated to `width`.

Exploratory Responsibility Profiles by Actor
Coding note: senior political leaders and military officials are
observed in all four treatment cells. Human-operator responsibility is
only observed in the human-operated condition, and AI-system
responsibility is only observed in the autonomous-AI condition. For that
reason, this plot compares responsibility levels descriptively within
each actor panel rather than treating all actor comparisons as if they
were asked of the same respondents in every condition.
responsibility_profile_data <- bind_rows(
prereg_analysis_data %>%
transmute(country_condition, weapons_condition, actor = "Senior political leaders", responsibility = as.numeric(resp_leader)),
prereg_analysis_data %>%
transmute(country_condition, weapons_condition, actor = "Military officials", responsibility = as.numeric(resp_military)),
prereg_analysis_data %>%
transmute(country_condition, weapons_condition, actor = "Human operator", responsibility = as.numeric(resp_pilot)),
prereg_analysis_data %>%
transmute(country_condition, weapons_condition, actor = "AI weapons system", responsibility = as.numeric(resp_ai))
) %>%
filter(!is.na(responsibility)) %>%
mutate(
country_condition = factor(
country_condition,
levels = c("Chinese strike / U.S. victim", "U.S. strike / Chinese victim"),
labels = c("Chinese strike", "U.S. strike")
),
weapons_condition = factor(weapons_condition, levels = c("Human-operated", "Autonomous AI")),
actor = factor(
actor,
levels = c("Senior political leaders", "Military officials", "Human operator", "AI weapons system")
)
)
responsibility_profile_summary <- responsibility_profile_data %>%
group_by(actor, country_condition, weapons_condition) %>%
summarize(
n = n(),
mean = mean(responsibility),
se = sd(responsibility) / sqrt(n),
ci_low = mean - 1.96 * se,
ci_high = mean + 1.96 * se,
.groups = "drop"
)
kable(
responsibility_profile_summary,
digits = 2,
caption = "Descriptive responsibility means and 95% confidence intervals by actor and experimental condition."
)
Descriptive responsibility means and 95% confidence intervals
by actor and experimental condition.
| Senior political leaders |
Chinese strike |
Human-operated |
728 |
74.64 |
0.87 |
72.94 |
76.34 |
| Senior political leaders |
Chinese strike |
Autonomous AI |
729 |
74.83 |
0.91 |
73.04 |
76.62 |
| Senior political leaders |
U.S. strike |
Human-operated |
720 |
69.63 |
0.98 |
67.72 |
71.55 |
| Senior political leaders |
U.S. strike |
Autonomous AI |
720 |
71.28 |
1.00 |
69.32 |
73.23 |
| Military officials |
Chinese strike |
Human-operated |
728 |
74.82 |
0.86 |
73.14 |
76.50 |
| Military officials |
Chinese strike |
Autonomous AI |
728 |
76.09 |
0.87 |
74.38 |
77.79 |
| Military officials |
U.S. strike |
Human-operated |
721 |
74.14 |
0.85 |
72.47 |
75.81 |
| Military officials |
U.S. strike |
Autonomous AI |
722 |
74.45 |
0.90 |
72.68 |
76.22 |
| Human operator |
Chinese strike |
Human-operated |
728 |
70.74 |
0.99 |
68.80 |
72.68 |
| Human operator |
U.S. strike |
Human-operated |
718 |
68.67 |
0.98 |
66.75 |
70.60 |
| AI weapons system |
Chinese strike |
Autonomous AI |
723 |
65.41 |
1.17 |
63.12 |
67.70 |
| AI weapons system |
U.S. strike |
Autonomous AI |
712 |
66.94 |
1.16 |
64.67 |
69.21 |
ggplot(
responsibility_profile_summary,
aes(x = weapons_condition, y = mean, color = country_condition, group = country_condition)
) +
geom_line(linewidth = 0.9, alpha = 0.45, na.rm = TRUE) +
geom_point(size = 2.8) +
geom_errorbar(aes(ymin = ci_low, ymax = ci_high), width = 0.08, linewidth = 0.7) +
facet_wrap(~ actor, ncol = 2) +
scale_color_manual(
values = c("Chinese strike" = "#A63A33", "U.S. strike" = "#235A8C"),
name = "Country scenario"
) +
coord_cartesian(ylim = c(50, 85)) +
labs(
title = "Responsibility Profiles by Actor and Condition",
x = "Weapons-system condition",
y = "Perceived responsibility",
caption = "Error bars are 95% confidence intervals. Human-operator and AI-system items are condition-specific."
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top",
panel.grid.major.x = element_blank(),
strip.text = element_text(face = "bold")
)
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?
## `geom_line()`: Each group consists of only one observation.
## ℹ Do you need to adjust the group aesthetic?

Exploratory Moderation Models
These models extend the primary specification by interacting the
country-scenario indicator, autonomous-AI indicator, and moderator.
Continuous moderators are demeaned. Models include Verasight demographic
controls; moderation models not focused on party identification also
control for pid_republican.
moderation_ai_comfort_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * ai_comfort_c +
pid_republican + age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_ai_comfort_vcov <- vcovHC(moderation_ai_comfort_model, type = "HC2")
moderation_ai_comfort_coeftest <- coeftest(moderation_ai_comfort_model, vcov. = moderation_ai_comfort_vcov)
moderation_ai_comfort_ci <- coefci(moderation_ai_comfort_model, vcov. = moderation_ai_comfort_vcov)
moderation_ai_comfort_results <- data.frame(
term = rownames(moderation_ai_comfort_coeftest),
estimate = moderation_ai_comfort_coeftest[, 1],
hc2_se = moderation_ai_comfort_coeftest[, 2],
statistic = moderation_ai_comfort_coeftest[, 3],
p_value = moderation_ai_comfort_coeftest[, 4],
ci_low = moderation_ai_comfort_ci[, 1],
ci_high = moderation_ai_comfort_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:ai_comfort_c") %>%
mutate(moderator = "AI comfort", .before = term)
moderation_us_ai_effectiveness_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * us_ai_effectiveness_c +
pid_republican + age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_us_ai_effectiveness_vcov <- vcovHC(moderation_us_ai_effectiveness_model, type = "HC2")
moderation_us_ai_effectiveness_coeftest <- coeftest(moderation_us_ai_effectiveness_model, vcov. = moderation_us_ai_effectiveness_vcov)
moderation_us_ai_effectiveness_ci <- coefci(moderation_us_ai_effectiveness_model, vcov. = moderation_us_ai_effectiveness_vcov)
moderation_us_ai_effectiveness_results <- data.frame(
term = rownames(moderation_us_ai_effectiveness_coeftest),
estimate = moderation_us_ai_effectiveness_coeftest[, 1],
hc2_se = moderation_us_ai_effectiveness_coeftest[, 2],
statistic = moderation_us_ai_effectiveness_coeftest[, 3],
p_value = moderation_us_ai_effectiveness_coeftest[, 4],
ci_low = moderation_us_ai_effectiveness_ci[, 1],
ci_high = moderation_us_ai_effectiveness_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:us_ai_effectiveness_c") %>%
mutate(moderator = "U.S. AI effectiveness", .before = term)
moderation_china_ai_effectiveness_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * china_ai_effectiveness_c +
pid_republican + age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_china_ai_effectiveness_vcov <- vcovHC(moderation_china_ai_effectiveness_model, type = "HC2")
moderation_china_ai_effectiveness_coeftest <- coeftest(moderation_china_ai_effectiveness_model, vcov. = moderation_china_ai_effectiveness_vcov)
moderation_china_ai_effectiveness_ci <- coefci(moderation_china_ai_effectiveness_model, vcov. = moderation_china_ai_effectiveness_vcov)
moderation_china_ai_effectiveness_results <- data.frame(
term = rownames(moderation_china_ai_effectiveness_coeftest),
estimate = moderation_china_ai_effectiveness_coeftest[, 1],
hc2_se = moderation_china_ai_effectiveness_coeftest[, 2],
statistic = moderation_china_ai_effectiveness_coeftest[, 3],
p_value = moderation_china_ai_effectiveness_coeftest[, 4],
ci_low = moderation_china_ai_effectiveness_ci[, 1],
ci_high = moderation_china_ai_effectiveness_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:china_ai_effectiveness_c") %>%
mutate(moderator = "Chinese AI effectiveness", .before = term)
moderation_southkorea_ai_effectiveness_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * southkorea_ai_effectiveness_c +
pid_republican + age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_southkorea_ai_effectiveness_vcov <- vcovHC(moderation_southkorea_ai_effectiveness_model, type = "HC2")
moderation_southkorea_ai_effectiveness_coeftest <- coeftest(moderation_southkorea_ai_effectiveness_model, vcov. = moderation_southkorea_ai_effectiveness_vcov)
moderation_southkorea_ai_effectiveness_ci <- coefci(moderation_southkorea_ai_effectiveness_model, vcov. = moderation_southkorea_ai_effectiveness_vcov)
moderation_southkorea_ai_effectiveness_results <- data.frame(
term = rownames(moderation_southkorea_ai_effectiveness_coeftest),
estimate = moderation_southkorea_ai_effectiveness_coeftest[, 1],
hc2_se = moderation_southkorea_ai_effectiveness_coeftest[, 2],
statistic = moderation_southkorea_ai_effectiveness_coeftest[, 3],
p_value = moderation_southkorea_ai_effectiveness_coeftest[, 4],
ci_low = moderation_southkorea_ai_effectiveness_ci[, 1],
ci_high = moderation_southkorea_ai_effectiveness_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:southkorea_ai_effectiveness_c") %>%
mutate(moderator = "South Korean AI effectiveness", .before = term)
moderation_relative_china_us_ai_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * relative_china_us_ai_c +
pid_republican + age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_relative_china_us_ai_vcov <- vcovHC(moderation_relative_china_us_ai_model, type = "HC2")
moderation_relative_china_us_ai_coeftest <- coeftest(moderation_relative_china_us_ai_model, vcov. = moderation_relative_china_us_ai_vcov)
moderation_relative_china_us_ai_ci <- coefci(moderation_relative_china_us_ai_model, vcov. = moderation_relative_china_us_ai_vcov)
moderation_relative_china_us_ai_results <- data.frame(
term = rownames(moderation_relative_china_us_ai_coeftest),
estimate = moderation_relative_china_us_ai_coeftest[, 1],
hc2_se = moderation_relative_china_us_ai_coeftest[, 2],
statistic = moderation_relative_china_us_ai_coeftest[, 3],
p_value = moderation_relative_china_us_ai_coeftest[, 4],
ci_low = moderation_relative_china_us_ai_ci[, 1],
ci_high = moderation_relative_china_us_ai_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:relative_china_us_ai_c") %>%
mutate(moderator = "Chinese minus U.S. AI effectiveness", .before = term)
moderation_pid_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * pid_republican +
ai_comfort_c + relative_china_us_ai_c +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = prereg_primary_data
)
moderation_pid_vcov <- vcovHC(moderation_pid_model, type = "HC2")
moderation_pid_coeftest <- coeftest(moderation_pid_model, vcov. = moderation_pid_vcov)
moderation_pid_ci <- coefci(moderation_pid_model, vcov. = moderation_pid_vcov)
moderation_pid_results <- data.frame(
term = rownames(moderation_pid_coeftest),
estimate = moderation_pid_coeftest[, 1],
hc2_se = moderation_pid_coeftest[, 2],
statistic = moderation_pid_coeftest[, 3],
p_value = moderation_pid_coeftest[, 4],
ci_low = moderation_pid_ci[, 1],
ci_high = moderation_pid_ci[, 2],
row.names = NULL
) %>%
filter(term == "country_scenario:autonomous_ai:pid_republican") %>%
mutate(moderator = "Party identification", .before = term)
moderation_results <- bind_rows(
moderation_ai_comfort_results,
moderation_us_ai_effectiveness_results,
moderation_china_ai_effectiveness_results,
moderation_southkorea_ai_effectiveness_results,
moderation_relative_china_us_ai_results,
moderation_pid_results
)
kable(
moderation_results,
digits = 3,
caption = "Focal three-way interaction terms from exploratory moderation models."
)
Focal three-way interaction terms from exploratory moderation
models.
| AI comfort |
country_scenario:autonomous_ai:ai_comfort_c |
4.428 |
1.773 |
2.498 |
0.013 |
0.952 |
7.904 |
| U.S. AI effectiveness |
country_scenario:autonomous_ai:us_ai_effectiveness_c |
0.086 |
0.081 |
1.063 |
0.288 |
-0.073 |
0.245 |
| Chinese AI effectiveness |
country_scenario:autonomous_ai:china_ai_effectiveness_c |
0.231 |
0.077 |
3.000 |
0.003 |
0.080 |
0.382 |
| South Korean AI effectiveness |
country_scenario:autonomous_ai:southkorea_ai_effectiveness_c |
0.223 |
0.083 |
2.677 |
0.007 |
0.060 |
0.386 |
| Chinese minus U.S. AI effectiveness |
country_scenario:autonomous_ai:relative_china_us_ai_c |
0.166 |
0.080 |
2.084 |
0.037 |
0.010 |
0.322 |
| Party identification |
country_scenario:autonomous_ai:pid_republican |
-1.276 |
3.728 |
-0.342 |
0.732 |
-8.585 |
6.033 |
if (nrow(moderation_results) > 0) {
moderation_plot_data <- moderation_results %>%
mutate(
moderator_term = ifelse(
term == "country_scenario:autonomous_ai:pid_republican",
"Republican vs. Democrat/Independent",
moderator
),
moderator_term = factor(moderator_term, levels = rev(unique(moderator_term)))
)
ggplot(moderation_plot_data, aes(x = estimate, y = moderator_term)) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray55") +
geom_errorbarh(aes(xmin = ci_low, xmax = ci_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 2.8) +
labs(
title = "Exploratory Moderation of the Treatment Interaction",
x = "Estimated three-way interaction",
y = NULL,
caption = "Points are focal three-way interaction estimates; error bars are 95% CIs using HC2 standard errors."
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank()
)
}
## `height` was translated to `width`.

Exploratory Partisan Polarization
This exploratory analysis uses the three-category party
identification variable to show whether perceived intentionality differs
across Democrats, Independents, and Republicans within each experimental
cell. The model is exploratory because the primary preregistered
specification uses the binary pid_republican control rather
than estimating separate treatment patterns for each party group.
polarization_data <- prereg_primary_data %>%
mutate(
pid_three_category = factor(pid, levels = c("Democrat", "Independent", "Republican")),
country_condition = factor(
country_condition,
levels = c("Chinese strike / U.S. victim", "U.S. strike / Chinese victim"),
labels = c("Chinese strike", "U.S. strike")
),
weapons_condition = factor(weapons_condition, levels = c("Human-operated", "Autonomous AI"))
) %>%
filter(!is.na(pid_three_category))
polarization_model <- lm(
perceived_intentionality ~ country_scenario * autonomous_ai * pid_three_category +
ai_comfort_c + relative_china_us_ai_c +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = polarization_data
)
polarization_vcov <- vcovHC(polarization_model, type = "HC2")
polarization_coeftest <- coeftest(polarization_model, vcov. = polarization_vcov)
polarization_ci <- coefci(polarization_model, vcov. = polarization_vcov)
polarization_results <- data.frame(
term = rownames(polarization_coeftest),
estimate = polarization_coeftest[, 1],
hc2_se = polarization_coeftest[, 2],
statistic = polarization_coeftest[, 3],
p_value = polarization_coeftest[, 4],
ci_low = polarization_ci[, 1],
ci_high = polarization_ci[, 2],
row.names = NULL
) %>%
filter(grepl("pid_three_category", term))
polarization_summary <- polarization_data %>%
group_by(pid_three_category, country_condition, weapons_condition) %>%
summarize(
n = n(),
mean = mean(perceived_intentionality),
se = sd(perceived_intentionality) / sqrt(n),
ci_low = mean - 1.96 * se,
ci_high = mean + 1.96 * se,
.groups = "drop"
)
kable(
polarization_results,
digits = 3,
caption = "Exploratory party-identification terms from a three-category partisan moderation model with HC2 standard errors."
)
Exploratory party-identification terms from a three-category
partisan moderation model with HC2 standard errors.
| pid_three_categoryIndependent |
-0.127 |
2.769 |
-0.046 |
0.963 |
-5.556 |
5.302 |
| pid_three_categoryRepublican |
-4.051 |
2.003 |
-2.022 |
0.043 |
-7.978 |
-0.123 |
| country_scenario:pid_three_categoryIndependent |
-5.558 |
3.791 |
-1.466 |
0.143 |
-12.992 |
1.876 |
| country_scenario:pid_three_categoryRepublican |
7.589 |
2.733 |
2.776 |
0.006 |
2.229 |
12.948 |
| autonomous_ai:pid_three_categoryIndependent |
-2.382 |
4.023 |
-0.592 |
0.554 |
-10.271 |
5.506 |
| autonomous_ai:pid_three_categoryRepublican |
3.263 |
2.849 |
1.145 |
0.252 |
-2.324 |
8.850 |
| country_scenario:autonomous_ai:pid_three_categoryIndependent |
11.439 |
5.418 |
2.111 |
0.035 |
0.815 |
22.062 |
| country_scenario:autonomous_ai:pid_three_categoryRepublican |
1.304 |
3.915 |
0.333 |
0.739 |
-6.373 |
8.981 |
ggplot(
polarization_summary,
aes(x = weapons_condition, y = mean, color = country_condition, group = country_condition)
) +
geom_line(linewidth = 0.9, alpha = 0.45) +
geom_point(size = 2.8) +
geom_errorbar(aes(ymin = ci_low, ymax = ci_high), width = 0.08, linewidth = 0.7) +
facet_wrap(~ pid_three_category) +
scale_color_manual(
values = c("Chinese strike" = "#A63A33", "U.S. strike" = "#235A8C"),
name = "Country scenario"
) +
coord_cartesian(ylim = c(45, 85)) +
labs(
title = "Perceived Intentionality by Party Identification",
x = "Weapons-system condition",
y = "Perceived intentionality",
caption = "Exploratory descriptive means by party group. Error bars are 95% confidence intervals."
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top",
panel.grid.major.x = element_blank(),
strip.text = element_text(face = "bold")
)

Exploratory Downstream Association Models
The preregistration describes mediation-style analyses as exploratory
and associational. The following models test whether perceived
intentionality is associated with downstream escalation and
responsibility judgments, controlling for treatment assignment, AI
comfort, relative China-U.S. AI effectiveness, Republican
identification, and Verasight demographic controls.
prereg_association_data <- prereg_primary_data %>%
mutate(perceived_intentionality_c = perceived_intentionality - mean(perceived_intentionality, na.rm = TRUE))
downstream_escalation_likelihood_data <- prereg_association_data %>%
filter(!is.na(escalation_likelihood))
downstream_escalation_likelihood_model <- lm(
escalation_likelihood ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = downstream_escalation_likelihood_data
)
downstream_escalation_likelihood_vcov <- vcovHC(downstream_escalation_likelihood_model, type = "HC2")
downstream_escalation_likelihood_coeftest <- coeftest(downstream_escalation_likelihood_model, vcov. = downstream_escalation_likelihood_vcov)
downstream_escalation_likelihood_ci <- coefci(downstream_escalation_likelihood_model, vcov. = downstream_escalation_likelihood_vcov)
downstream_escalation_likelihood_results <- data.frame(
term = rownames(downstream_escalation_likelihood_coeftest),
estimate = downstream_escalation_likelihood_coeftest[, 1],
hc2_se = downstream_escalation_likelihood_coeftest[, 2],
statistic = downstream_escalation_likelihood_coeftest[, 3],
p_value = downstream_escalation_likelihood_coeftest[, 4],
ci_low = downstream_escalation_likelihood_ci[, 1],
ci_high = downstream_escalation_likelihood_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Likelihood of escalation", .before = term)
downstream_escalation_justifiability_data <- prereg_association_data %>%
filter(!is.na(escalation_justifiability))
downstream_escalation_justifiability_model <- lm(
escalation_justifiability ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = downstream_escalation_justifiability_data
)
downstream_escalation_justifiability_vcov <- vcovHC(downstream_escalation_justifiability_model, type = "HC2")
downstream_escalation_justifiability_coeftest <- coeftest(downstream_escalation_justifiability_model, vcov. = downstream_escalation_justifiability_vcov)
downstream_escalation_justifiability_ci <- coefci(downstream_escalation_justifiability_model, vcov. = downstream_escalation_justifiability_vcov)
downstream_escalation_justifiability_results <- data.frame(
term = rownames(downstream_escalation_justifiability_coeftest),
estimate = downstream_escalation_justifiability_coeftest[, 1],
hc2_se = downstream_escalation_justifiability_coeftest[, 2],
statistic = downstream_escalation_justifiability_coeftest[, 3],
p_value = downstream_escalation_justifiability_coeftest[, 4],
ci_low = downstream_escalation_justifiability_ci[, 1],
ci_high = downstream_escalation_justifiability_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Justifiability of escalation", .before = term)
downstream_results <- bind_rows(
downstream_escalation_likelihood_results,
downstream_escalation_justifiability_results
)
prereg_responsibility_association_data <- bind_rows(
prereg_association_data %>%
mutate(actor = "Senior political leaders", responsibility = as.numeric(resp_leader)),
prereg_association_data %>%
mutate(actor = "Military officials", responsibility = as.numeric(resp_military)),
prereg_association_data %>%
mutate(actor = "Human operator", responsibility = as.numeric(resp_pilot)),
prereg_association_data %>%
mutate(actor = "AI weapons system", responsibility = as.numeric(resp_ai))
) %>%
filter(!is.na(responsibility))
responsibility_association_senior_political_leaders_data <- prereg_responsibility_association_data %>%
filter(actor == "Senior political leaders",
!is.na(perceived_intentionality_c))
responsibility_association_senior_political_leaders_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = responsibility_association_senior_political_leaders_data
)
responsibility_association_senior_political_leaders_vcov <- vcovHC(responsibility_association_senior_political_leaders_model, type = "HC2")
responsibility_association_senior_political_leaders_coeftest <- coeftest(responsibility_association_senior_political_leaders_model, vcov. = responsibility_association_senior_political_leaders_vcov)
responsibility_association_senior_political_leaders_ci <- coefci(responsibility_association_senior_political_leaders_model, vcov. = responsibility_association_senior_political_leaders_vcov)
responsibility_association_senior_political_leaders_results <- data.frame(
term = rownames(responsibility_association_senior_political_leaders_coeftest),
estimate = responsibility_association_senior_political_leaders_coeftest[, 1],
hc2_se = responsibility_association_senior_political_leaders_coeftest[, 2],
statistic = responsibility_association_senior_political_leaders_coeftest[, 3],
p_value = responsibility_association_senior_political_leaders_coeftest[, 4],
ci_low = responsibility_association_senior_political_leaders_ci[, 1],
ci_high = responsibility_association_senior_political_leaders_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Responsibility: Senior political leaders", .before = term)
responsibility_association_military_officials_data <- prereg_responsibility_association_data %>%
filter(actor == "Military officials",
!is.na(perceived_intentionality_c))
responsibility_association_military_officials_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = responsibility_association_military_officials_data
)
responsibility_association_military_officials_vcov <- vcovHC(responsibility_association_military_officials_model, type = "HC2")
responsibility_association_military_officials_coeftest <- coeftest(responsibility_association_military_officials_model, vcov. = responsibility_association_military_officials_vcov)
responsibility_association_military_officials_ci <- coefci(responsibility_association_military_officials_model, vcov. = responsibility_association_military_officials_vcov)
responsibility_association_military_officials_results <- data.frame(
term = rownames(responsibility_association_military_officials_coeftest),
estimate = responsibility_association_military_officials_coeftest[, 1],
hc2_se = responsibility_association_military_officials_coeftest[, 2],
statistic = responsibility_association_military_officials_coeftest[, 3],
p_value = responsibility_association_military_officials_coeftest[, 4],
ci_low = responsibility_association_military_officials_ci[, 1],
ci_high = responsibility_association_military_officials_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Responsibility: Military officials", .before = term)
responsibility_association_human_operator_data <- prereg_responsibility_association_data %>%
filter(actor == "Human operator",
!is.na(perceived_intentionality_c))
responsibility_association_human_operator_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = responsibility_association_human_operator_data
)
responsibility_association_human_operator_vcov <- vcovHC(responsibility_association_human_operator_model, type = "HC2")
responsibility_association_human_operator_coeftest <- coeftest(responsibility_association_human_operator_model, vcov. = responsibility_association_human_operator_vcov)
responsibility_association_human_operator_ci <- coefci(responsibility_association_human_operator_model, vcov. = responsibility_association_human_operator_vcov)
responsibility_association_human_operator_results <- data.frame(
term = rownames(responsibility_association_human_operator_coeftest),
estimate = responsibility_association_human_operator_coeftest[, 1],
hc2_se = responsibility_association_human_operator_coeftest[, 2],
statistic = responsibility_association_human_operator_coeftest[, 3],
p_value = responsibility_association_human_operator_coeftest[, 4],
ci_low = responsibility_association_human_operator_ci[, 1],
ci_high = responsibility_association_human_operator_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Responsibility: Human operator", .before = term)
responsibility_association_ai_weapons_system_data <- prereg_responsibility_association_data %>%
filter(actor == "AI weapons system",
!is.na(perceived_intentionality_c))
responsibility_association_ai_weapons_system_model <- lm(
responsibility ~ country_scenario * autonomous_ai +
perceived_intentionality_c + ai_comfort_c + relative_china_us_ai_c + pid_republican +
age_ordinal + gender_female + education_ordinal + income_ordinal +
race_white + hispanic + metro,
data = responsibility_association_ai_weapons_system_data
)
responsibility_association_ai_weapons_system_vcov <- vcovHC(responsibility_association_ai_weapons_system_model, type = "HC2")
responsibility_association_ai_weapons_system_coeftest <- coeftest(responsibility_association_ai_weapons_system_model, vcov. = responsibility_association_ai_weapons_system_vcov)
responsibility_association_ai_weapons_system_ci <- coefci(responsibility_association_ai_weapons_system_model, vcov. = responsibility_association_ai_weapons_system_vcov)
responsibility_association_ai_weapons_system_results <- data.frame(
term = rownames(responsibility_association_ai_weapons_system_coeftest),
estimate = responsibility_association_ai_weapons_system_coeftest[, 1],
hc2_se = responsibility_association_ai_weapons_system_coeftest[, 2],
statistic = responsibility_association_ai_weapons_system_coeftest[, 3],
p_value = responsibility_association_ai_weapons_system_coeftest[, 4],
ci_low = responsibility_association_ai_weapons_system_ci[, 1],
ci_high = responsibility_association_ai_weapons_system_ci[, 2],
row.names = NULL
) %>%
filter(term == "perceived_intentionality_c") %>%
mutate(outcome = "Responsibility: AI weapons system", .before = term)
responsibility_association_results <- bind_rows(
responsibility_association_senior_political_leaders_results,
responsibility_association_military_officials_results,
responsibility_association_human_operator_results,
responsibility_association_ai_weapons_system_results
)
kable(
bind_rows(downstream_results, responsibility_association_results),
digits = 3,
caption = "Association between perceived intentionality and downstream judgments using HC2 standard errors."
)
Association between perceived intentionality and downstream
judgments using HC2 standard errors.
| Likelihood of escalation |
perceived_intentionality_c |
0.323 |
0.019 |
17.370 |
0.000 |
0.286 |
0.359 |
| Justifiability of escalation |
perceived_intentionality_c |
0.405 |
0.021 |
18.872 |
0.000 |
0.363 |
0.448 |
| Responsibility: Senior political leaders |
perceived_intentionality_c |
0.384 |
0.021 |
18.338 |
0.000 |
0.343 |
0.425 |
| Responsibility: Military officials |
perceived_intentionality_c |
0.273 |
0.020 |
13.330 |
0.000 |
0.233 |
0.313 |
| Responsibility: Human operator |
perceived_intentionality_c |
0.143 |
0.033 |
4.351 |
0.000 |
0.079 |
0.208 |
| Responsibility: AI weapons system |
perceived_intentionality_c |
-0.012 |
0.037 |
-0.313 |
0.754 |
-0.085 |
0.062 |
prereg_downstream_plot_data <- bind_rows(downstream_results, responsibility_association_results) %>%
mutate(outcome = factor(outcome, levels = rev(outcome)))
ggplot(prereg_downstream_plot_data, aes(x = estimate, y = outcome)) +
geom_vline(xintercept = 0, linewidth = 0.5, color = "gray55") +
geom_errorbarh(aes(xmin = ci_low, xmax = ci_high), height = 0.14, linewidth = 0.8) +
geom_point(size = 2.8) +
labs(
title = "Association Between Intentionality and Downstream Judgments",
x = "Estimated association with perceived intentionality",
y = NULL,
caption = "Associational models control for treatment assignment, preregistered covariates, and demographic controls. Error bars are 95% CIs using HC2 standard errors."
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
panel.grid.major.y = element_blank()
)
## `height` was translated to `width`.

Exploratory Distributional Checks for Intentionality
The primary analyses focus on average treatment effects. These plots
look at the full distribution of perceived intentionality by
experimental condition. This helps diagnose whether differences in means
reflect broad shifts across respondents or changes concentrated at
particular parts of the 0-to-100 scale.
intentionality_distribution_data <- prereg_analysis_data %>%
mutate(
country_condition = factor(
country_condition,
levels = c("Chinese strike / U.S. victim", "U.S. strike / Chinese victim"),
labels = c("Chinese strike", "U.S. strike")
),
weapons_condition = factor(weapons_condition, levels = c("Human-operated", "Autonomous AI"))
)
intentionality_quantiles <- intentionality_distribution_data %>%
group_by(country_condition, weapons_condition) %>%
summarize(
n = n(),
mean = mean(perceived_intentionality, na.rm = TRUE),
p10 = quantile(perceived_intentionality, 0.10, na.rm = TRUE),
p25 = quantile(perceived_intentionality, 0.25, na.rm = TRUE),
median = median(perceived_intentionality, na.rm = TRUE),
p75 = quantile(perceived_intentionality, 0.75, na.rm = TRUE),
p90 = quantile(perceived_intentionality, 0.90, na.rm = TRUE),
.groups = "drop"
)
kable(
intentionality_quantiles,
digits = 2,
caption = "Distributional summaries for perceived intentionality by experimental cell."
)
Distributional summaries for perceived intentionality by
experimental cell.
| Chinese strike |
Human-operated |
737 |
72.11 |
46.0 |
51 |
75 |
94 |
100 |
| Chinese strike |
Autonomous AI |
737 |
62.09 |
33.6 |
50 |
59 |
80 |
99 |
| U.S. strike |
Human-operated |
733 |
62.83 |
36.2 |
50 |
59 |
84 |
99 |
| U.S. strike |
Autonomous AI |
728 |
54.21 |
17.0 |
43 |
51 |
71 |
92 |
ggplot(
intentionality_distribution_data,
aes(x = perceived_intentionality, fill = country_condition, color = country_condition)
) +
geom_density(alpha = 0.20, linewidth = 0.8, adjust = 1.1, na.rm = TRUE) +
facet_wrap(~ weapons_condition) +
scale_fill_manual(
values = c("Chinese strike" = "#A63A33", "U.S. strike" = "#235A8C"),
name = "Country scenario"
) +
scale_color_manual(
values = c("Chinese strike" = "#A63A33", "U.S. strike" = "#235A8C"),
name = "Country scenario"
) +
scale_x_continuous(limits = c(0, 100), breaks = seq(0, 100, 20)) +
labs(
title = "Distribution of Perceived Intentionality by Condition",
x = "Perceived intentionality",
y = "Density",
caption = "Density plots show the full outcome distribution rather than only the mean."
) +
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "top",
panel.grid.minor = element_blank(),
strip.text = element_text(face = "bold")
)
