diff --git a/README.md b/README.md
index 80eaf29..d464c38 100644
--- a/README.md
+++ b/README.md
@@ -368,6 +368,7 @@ Implemented measures include:
- **Information sufficiency**: perceived adequacy of available information before the reveal.
- **Structural impact**: post-reveal perceived effect of the hidden cost difference.
- **Perspective change**: post-reveal reported change in views of lower-scoring players.
+- **Remembered initial judgment**: post-reveal memory of the participant's pre-reveal attribution, responsibility rating, constraint-suspicion rating, and confidence in that memory.
## Computed metrics
@@ -384,6 +385,11 @@ Computed metrics are derived from game and survey responses for prototype analys
- **`burden`**: total treatment cost paid divided by total available income.
- **`careAvoidance`**: skipped treatments plus half of partial treatments.
- **`attributionCategoryShift`**: pre-reveal primary attribution compared with post-reveal revised primary attribution.
+- **`rememberedResponsibilityError`**: remembered pre-reveal responsibility minus the original pre-reveal responsibility rating.
+- **`rememberedConstraintSuspicionError`**: remembered pre-reveal constraint suspicion minus the original pre-reveal constraint-suspicion rating.
+- **`rememberedPrimaryAttributionMatchesOriginal`**: whether remembered and original pre-reveal primary attribution match.
+- **`memoryConfidence`**: confidence in memory of the initial interpretation.
+- **`memoryDistortionMagnitude`**: absolute remembered responsibility error plus absolute remembered constraint-suspicion error.
## Contact and collaboration
diff --git a/components/PostRevealSurveyForm.tsx b/components/PostRevealSurveyForm.tsx
index d00d76e..132da83 100644
--- a/components/PostRevealSurveyForm.tsx
+++ b/components/PostRevealSurveyForm.tsx
@@ -8,6 +8,15 @@ import { HelperNote, LikertQuestion, PrimaryButton, SingleChoiceQuestion, TextQu
import { getStoredSession, saveStoredSession } from "@/utils/session";
import type { PostRevealSurveyAnswers, ResearchSession } from "@/types/research";
+const rememberedPrimaryAttributionOptions = [
+ "They made less effective decisions during the game",
+ "They accepted too much risk",
+ "Factors not shown in the score table may have influenced the results",
+ "Random variation or luck may have played a role",
+ "I did not have enough information to judge",
+ "I am not sure what I initially thought",
+];
+
const revisedPrimaryAttributionOptions = [
"Their decisions still seem to be the main explanation",
"Hidden cost conditions seem to be the main explanation",
@@ -17,6 +26,10 @@ const revisedPrimaryAttributionOptions = [
];
const initialAnswers: PostRevealSurveyAnswers = {
+ rememberedPrimaryAttribution: "",
+ rememberedIndividualResponsibility: 0,
+ rememberedConstraintSuspicion: 0,
+ rememberedConfidence: 0,
revisedPrimaryAttribution: "",
revisedIndividualResponsibility: 0,
perceivedStructuralImpact: 0,
@@ -56,7 +69,7 @@ export function PostRevealSurveyForm() {
saveStoredSession(nextSession);
setSession(nextSession);
- setAnswers(nextSession.postRevealSurvey ?? initialAnswers);
+ setAnswers({ ...initialAnswers, ...nextSession.postRevealSurvey });
}, [router]);
useEffect(() => {
@@ -71,6 +84,10 @@ export function PostRevealSurveyForm() {
const openLength = answers.openRevision.trim().length;
const isComplete =
+ answers.rememberedPrimaryAttribution.length > 0 &&
+ answers.rememberedIndividualResponsibility > 0 &&
+ answers.rememberedConstraintSuspicion > 0 &&
+ answers.rememberedConfidence > 0 &&
answers.revisedPrimaryAttribution.length > 0 &&
answers.revisedIndividualResponsibility > 0 &&
answers.perceivedStructuralImpact > 0 &&
@@ -117,22 +134,34 @@ export function PostRevealSurveyForm() {
Please answer after considering the cost rule that was just disclosed. These responses describe interpretations, not personal worth, fairness, or character.
updateAnswer("rememberedPrimaryAttribution", value)}
+ />
+
+ updateAnswer("rememberedIndividualResponsibility", value)} />
+ updateAnswer("rememberedConstraintSuspicion", value)} />
+ updateAnswer("rememberedConfidence", value)} />
+
+ updateAnswer("revisedPrimaryAttribution", value)}
/>
- updateAnswer("revisedIndividualResponsibility", value)} />
- updateAnswer("perceivedStructuralImpact", value)} />
- updateAnswer("postProtestLegitimacy", value)} />
- updateAnswer("postRuleCorrectionSupport", value)} />
- updateAnswer("postRedistributionSupport", value)} />
- updateAnswer("initialJudgmentAccuracy", value)} />
- updateAnswer("perspectiveChange", value)} />
+ updateAnswer("revisedIndividualResponsibility", value)} />
+ updateAnswer("perceivedStructuralImpact", value)} />
+ updateAnswer("postProtestLegitimacy", value)} />
+ updateAnswer("postRuleCorrectionSupport", value)} />
+ updateAnswer("postRedistributionSupport", value)} />
+ updateAnswer("initialJudgmentAccuracy", value)} />
+ updateAnswer("perspectiveChange", value)} />
- updateAnswer("openRevision", value)} minLength={10} maxLength={500} />
+ updateAnswer("openRevision", value)} minLength={10} maxLength={500} />
{showValidation && !isComplete ? Please answer all closed-ended items and write 10–500 characters in the revision. Your draft has been saved in this browser. : null}
diff --git a/components/ResultsTable.tsx b/components/ResultsTable.tsx
index de901fd..63b10eb 100644
--- a/components/ResultsTable.tsx
+++ b/components/ResultsTable.tsx
@@ -111,7 +111,7 @@ function IndividualResults({
postRevealSurvey: PostRevealSurveyAnswers;
}) {
const gameSummary = calculateGameSummary(game);
- const computedMetrics = calculateComputedResearchMetrics({ game, preRevealSurvey, postRevealSurvey });
+ const computedMetrics = calculateComputedResearchMetrics({ game, preRevealSurvey, postRevealSurvey, preRevealSurveyOriginal: session.preRevealSurveyOriginal });
const interpretations = buildParticipantInterpretation(computedMetrics);
return (
@@ -221,6 +221,11 @@ function MetricsGrid({ metrics }: { metrics: ComputedResearchMetrics }) {
["Cost burden ratio", metrics.burden],
["Care avoidance index", metrics.careAvoidance],
["Attribution category shift", `${metrics.attributionCategoryShift.pre} → ${metrics.attributionCategoryShift.post}`],
+ ["Remembered responsibility error", metrics.rememberedResponsibilityError],
+ ["Remembered constraint suspicion error", metrics.rememberedConstraintSuspicionError],
+ ["Remembered attribution matches original", metrics.rememberedPrimaryAttributionMatchesOriginal ? "Yes" : "No"],
+ ["Memory confidence", metrics.memoryConfidence],
+ ["Memory distortion magnitude", metrics.memoryDistortionMagnitude],
] as const;
return (
diff --git a/docs/RESEARCH_NOTES.md b/docs/RESEARCH_NOTES.md
index e389df6..ad1ac91 100644
--- a/docs/RESEARCH_NOTES.md
+++ b/docs/RESEARCH_NOTES.md
@@ -40,6 +40,7 @@ Computed metrics summarize analysis-ready outcomes, including:
- `ruleCorrectionSupportShift` — change in support for correcting the rules.
- `redistributionSupportShift` — change in redistributive support.
- `certaintyCorrection`, `informationCaution`, and `perspectiveChange` — additional post-reveal interpretation and reflection measures.
+- `rememberedResponsibilityError`, `rememberedConstraintSuspicionError`, `rememberedPrimaryAttributionMatchesOriginal`, `memoryConfidence`, and `memoryDistortionMagnitude` — post-reveal memory-of-initial-judgment measures compared against the original pre-reveal responses when available.
## Ethics and limitations
diff --git a/lib/adminSubmissions.ts b/lib/adminSubmissions.ts
index b8164d6..bd3ab3c 100644
--- a/lib/adminSubmissions.ts
+++ b/lib/adminSubmissions.ts
@@ -313,12 +313,20 @@ const CSV_COLUMNS: CsvColumn[] = [
payloadColumn("certainty_correction", ["computedMetrics", "certaintyCorrection"]),
payloadColumn("information_caution", ["computedMetrics", "informationCaution"]),
payloadColumn("perspective_change", ["computedMetrics", "perspectiveChange"]),
+ payloadColumn("remembered_responsibility_error", ["computedMetrics", "rememberedResponsibilityError"]),
+ payloadColumn("remembered_constraint_suspicion_error", ["computedMetrics", "rememberedConstraintSuspicionError"]),
+ payloadColumn("remembered_primary_attribution_matches_original", ["computedMetrics", "rememberedPrimaryAttributionMatchesOriginal"]),
+ payloadColumn("memory_confidence", ["computedMetrics", "memoryConfidence"]),
+ payloadColumn("memory_distortion_magnitude", ["computedMetrics", "memoryDistortionMagnitude"]),
payloadColumn("pre_primary_attribution", ["preRevealSurvey", "primaryAttribution"]),
+ payloadColumn("remembered_primary_attribution", ["postRevealSurvey", "rememberedPrimaryAttribution"]),
payloadColumn("post_revised_primary_attribution", ["postRevealSurvey", "revisedPrimaryAttribution"]),
payloadColumn("pre_individual_responsibility", ["preRevealSurvey", "individualResponsibility"]),
payloadColumn("post_revised_individual_responsibility", ["postRevealSurvey", "revisedIndividualResponsibility"]),
+ payloadColumn("remembered_individual_responsibility", ["postRevealSurvey", "rememberedIndividualResponsibility"]),
payloadColumn("pre_constraint_suspicion", ["preRevealSurvey", "constraintSuspicion"]),
payloadColumn("post_perceived_structural_impact", ["postRevealSurvey", "perceivedStructuralImpact"]),
+ payloadColumn("remembered_constraint_suspicion", ["postRevealSurvey", "rememberedConstraintSuspicion"]),
payloadColumn("pre_protest_legitimacy", ["preRevealSurvey", "protestLegitimacy"]),
payloadColumn("post_protest_legitimacy", ["postRevealSurvey", "postProtestLegitimacy"]),
payloadColumn("pre_rule_correction_support", ["preRevealSurvey", "ruleCorrectionSupport"]),
@@ -326,6 +334,7 @@ const CSV_COLUMNS: CsvColumn[] = [
payloadColumn("pre_redistribution_support", ["preRevealSurvey", "redistributionSupport"]),
payloadColumn("post_redistribution_support", ["postRevealSurvey", "postRedistributionSupport"]),
payloadColumn("pre_confidence", ["preRevealSurvey", "confidence"]),
+ payloadColumn("remembered_confidence", ["postRevealSurvey", "rememberedConfidence"]),
payloadColumn("post_initial_judgment_accuracy", ["postRevealSurvey", "initialJudgmentAccuracy"]),
payloadColumn("pre_information_sufficiency", ["preRevealSurvey", "informationSufficiency"]),
payloadColumn("post_perspective_change", ["postRevealSurvey", "perspectiveChange"]),
diff --git a/lib/researchExportSchema.ts b/lib/researchExportSchema.ts
index cd026ac..775766b 100644
--- a/lib/researchExportSchema.ts
+++ b/lib/researchExportSchema.ts
@@ -122,6 +122,10 @@ export const preRevealSurveySchema = z
export const postRevealSurveySchema = z
.object({
+ rememberedPrimaryAttribution: z.string().min(1),
+ rememberedIndividualResponsibility: likertSchema,
+ rememberedConstraintSuspicion: likertSchema,
+ rememberedConfidence: likertSchema,
revisedPrimaryAttribution: z.string().min(1),
revisedIndividualResponsibility: likertSchema,
perceivedStructuralImpact: likertSchema,
@@ -148,6 +152,11 @@ export const computedMetricsSchema = z
careAvoidance: z.number(),
delayedReveal: z.boolean(),
standByInitialInterpretation: likertSchema.optional(),
+ rememberedResponsibilityError: z.number(),
+ rememberedConstraintSuspicionError: z.number(),
+ rememberedPrimaryAttributionMatchesOriginal: z.boolean(),
+ memoryConfidence: likertSchema,
+ memoryDistortionMagnitude: z.number().nonnegative(),
attributionCategoryShift: z
.object({
pre: z.string().min(1),
diff --git a/sample-data/complete-research-export.example.json b/sample-data/complete-research-export.example.json
index b989550..18ededf 100644
--- a/sample-data/complete-research-export.example.json
+++ b/sample-data/complete-research-export.example.json
@@ -1,6 +1,6 @@
{
- "exportVersion": "prototype-1.1",
- "schemaVersion": "research-export-v1",
+ "exportVersion": "prototype-1.2",
+ "schemaVersion": "hidden-cost-game-research-schema-3",
"sessionId": "hcg-example-session",
"consentVersion": "pilot-consent-v1",
"serverSubmissionStatus": "not_submitted",
@@ -143,6 +143,10 @@
"openExplanation": "This is fake sample text for validating a complete export."
},
"postRevealSurvey": {
+ "rememberedPrimaryAttribution": "individual choices",
+ "rememberedIndividualResponsibility": 4,
+ "rememberedConstraintSuspicion": 4,
+ "rememberedConfidence": 5,
"revisedPrimaryAttribution": "structural constraints",
"revisedIndividualResponsibility": 3,
"perceivedStructuralImpact": 6,
@@ -164,6 +168,12 @@
"perspectiveChange": 6,
"burden": 0.775,
"careAvoidance": 1.5,
+ "delayedReveal": false,
+ "rememberedResponsibilityError": -1,
+ "rememberedConstraintSuspicionError": 1,
+ "rememberedPrimaryAttributionMatchesOriginal": true,
+ "memoryConfidence": 5,
+ "memoryDistortionMagnitude": 2,
"attributionCategoryShift": {
"pre": "individual choices",
"post": "structural constraints"
diff --git a/types/research.ts b/types/research.ts
index e715e4f..44f560a 100644
--- a/types/research.ts
+++ b/types/research.ts
@@ -102,6 +102,10 @@ export type PreRevealSurveyAnswers = {
};
export type PostRevealSurveyAnswers = {
+ rememberedPrimaryAttribution: string;
+ rememberedIndividualResponsibility: number;
+ rememberedConstraintSuspicion: number;
+ rememberedConfidence: number;
revisedPrimaryAttribution: string;
revisedIndividualResponsibility: number;
perceivedStructuralImpact: number;
@@ -188,6 +192,11 @@ export interface ComputedResearchMetrics {
revisionMagnitude?: number;
delayedReveal: boolean;
standByInitialInterpretation?: number;
+ rememberedResponsibilityError: number;
+ rememberedConstraintSuspicionError: number;
+ rememberedPrimaryAttributionMatchesOriginal: boolean;
+ memoryConfidence: number;
+ memoryDistortionMagnitude: number;
}
export interface ResearchExportAssignedProfile {
diff --git a/utils/researchMetrics.ts b/utils/researchMetrics.ts
index 155824e..842e2b6 100644
--- a/utils/researchMetrics.ts
+++ b/utils/researchMetrics.ts
@@ -12,8 +12,8 @@ import type {
TreatmentChoiceCounts,
} from "@/types/research";
-export const RESEARCH_EXPORT_VERSION = "prototype-1.1";
-export const RESEARCH_SCHEMA_VERSION = "hidden-cost-game-research-schema-2";
+export const RESEARCH_EXPORT_VERSION = "prototype-1.2";
+export const RESEARCH_SCHEMA_VERSION = "hidden-cost-game-research-schema-3";
export const RESEARCH_CONSENT_VERSION = "pilot-consent-v1";
const choiceCountKeys: Record = {
@@ -43,7 +43,11 @@ export function isPostRevealSurveyComplete(survey: PostRevealSurveyAnswers | und
const openLength = survey?.openRevision.trim().length ?? 0;
return Boolean(
- survey?.revisedPrimaryAttribution &&
+ survey?.rememberedPrimaryAttribution &&
+ survey.rememberedIndividualResponsibility > 0 &&
+ survey.rememberedConstraintSuspicion > 0 &&
+ survey.rememberedConfidence > 0 &&
+ survey.revisedPrimaryAttribution &&
survey.revisedIndividualResponsibility > 0 &&
survey.perceivedStructuralImpact > 0 &&
survey.postProtestLegitimacy > 0 &&
@@ -114,6 +118,10 @@ export function calculateComputedResearchMetrics({
preRevealCommitment?: ResearchSession["preRevealCommitment"];
}): ComputedResearchMetrics {
const summary = calculateGameSummary(game);
+ const originalPreRevealSurvey = preRevealSurveyOriginal ?? preRevealSurvey;
+ const rememberedResponsibilityError = postRevealSurvey.rememberedIndividualResponsibility - originalPreRevealSurvey.individualResponsibility;
+ const rememberedConstraintSuspicionError = postRevealSurvey.rememberedConstraintSuspicion - originalPreRevealSurvey.constraintSuspicion;
+ const memoryDistortionMagnitude = Math.abs(rememberedResponsibilityError) + Math.abs(rememberedConstraintSuspicionError);
const responsibilityRevisionDelta = preRevealSurveyRevisedAfterReveal && preRevealSurveyOriginal ? preRevealSurveyRevisedAfterReveal.individualResponsibility - preRevealSurveyOriginal.individualResponsibility : undefined;
const constraintSuspicionRevisionDelta = preRevealSurveyRevisedAfterReveal && preRevealSurveyOriginal ? preRevealSurveyRevisedAfterReveal.constraintSuspicion - preRevealSurveyOriginal.constraintSuspicion : undefined;
const protestLegitimacyRevisionDelta = preRevealSurveyRevisedAfterReveal && preRevealSurveyOriginal ? preRevealSurveyRevisedAfterReveal.protestLegitimacy - preRevealSurveyOriginal.protestLegitimacy : undefined;
@@ -145,6 +153,11 @@ export function calculateComputedResearchMetrics({
careAvoidance: summary.skippedTreatmentChoices + 0.5 * summary.partialTreatmentChoices,
delayedReveal: revealTimingCondition?.condition === "delayed-reveal",
...(preRevealCommitment ? { standByInitialInterpretation: preRevealCommitment.standByInitialInterpretation } : {}),
+ rememberedResponsibilityError,
+ rememberedConstraintSuspicionError,
+ rememberedPrimaryAttributionMatchesOriginal: postRevealSurvey.rememberedPrimaryAttribution === originalPreRevealSurvey.primaryAttribution,
+ memoryConfidence: postRevealSurvey.rememberedConfidence,
+ memoryDistortionMagnitude: roundMetric(memoryDistortionMagnitude),
attributionCategoryShift: {
pre: preRevealSurvey.primaryAttribution,
post: postRevealSurvey.revisedPrimaryAttribution,