devaanand Claude Opus 5 (1M context) commited on
Commit
10425ec
·
1 Parent(s): 461b859

fix(constructs): verify MFQ against the source the review sheet omitted

Browse files

Checking whether the follow-up questions for the reviewer were fair
turned up that two of them were not.

The review sheet shipped with an EMPTY source_url for mfq_care and
mfq_fairness, so the reviewer had nothing to check those against and
correctly flagged it. That was our omission, not a missing document:
the MFQ30 is public, all four items in each construct match it
verbatim, and both are now verified with the source recorded. This also
settles the "differently than/from others" disagreement in favour of
the wording already stored.

Also confirmed independently, so the reviewer does not need to be asked:
the Subjective Happiness Scale PDF at the source_url we gave her does
read "Compared to most of my peers", exactly as she corrected it.

And for context on the two item-order findings: the APA measures-package
printing of the RSES numbers its items exactly as we store them, while
the reviewer's renumbering matches another widely-used printing. Same
version-mismatch pattern as Edmondson and the MFQ, so it is a question
about which printing to standardise on rather than an error either way.

83 verified (was 81), 11 unverified (was 13).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

CHANGELOG.md CHANGED
@@ -7,17 +7,17 @@ Format: [Keep a Changelog](https://keepachangelog.com/). User-visible changes on
7
  ### Changed
8
  - Construct library verified against the source publications. All 525 items across the
9
  94 constructs were reviewed (wording, reverse-scoring keys, subscale grouping,
10
- citations); 81 constructs are now marked verified and show who reviewed them and
11
  when, instead of the blanket "needs verification" flag every construct carried. The
12
  review corrected 61 reverse-scoring flags across 14 constructs (the library had 35
13
  flagged items, it now has 96), 7 item wordings, one subscale grouping in the SCS-SF,
14
  and a batch of dead or incomplete citation links. Corrected constructs ship as a new
15
  version: the picker offers the corrected one, and runs that used the earlier version
16
- still open, export, and reproduce exactly as before. 13 constructs stay flagged, each
17
- now saying why: two open wording questions (the IPIP scales and the K10), two where
18
- the review's proposed wording disagreed with the cited publication and the published
19
- wording was kept, two with unresolved item-ordering questions, and three with no
20
- reachable source document on file. (spec 0007)
21
 
22
  ### Added
23
  - Runs now warn when every item in a construct is reverse-scored. Scores are raw
 
7
  ### Changed
8
  - Construct library verified against the source publications. All 525 items across the
9
  94 constructs were reviewed (wording, reverse-scoring keys, subscale grouping,
10
+ citations); 83 constructs are now marked verified and show who reviewed them and
11
  when, instead of the blanket "needs verification" flag every construct carried. The
12
  review corrected 61 reverse-scoring flags across 14 constructs (the library had 35
13
  flagged items, it now has 96), 7 item wordings, one subscale grouping in the SCS-SF,
14
  and a batch of dead or incomplete citation links. Corrected constructs ship as a new
15
  version: the picker offers the corrected one, and runs that used the earlier version
16
+ still open, export, and reproduce exactly as before. 11 constructs stay flagged, each
17
+ now saying why: two open wording questions (the IPIP scales and the K10), one where the
18
+ review's proposed wording disagreed with the cited publication and the published wording
19
+ was kept, two with unresolved item-ordering questions, and two whose recorded source
20
+ document no longer resolves. (spec 0007)
21
 
22
  ### Added
23
  - Runs now warn when every item in a construct is reverse-scored. Scores are raw
README.md CHANGED
@@ -54,8 +54,8 @@ Configuration: copy `.env.example` to `.env` and fill what you need.
54
  storage is ephemeral and the instance may reset.
55
  - The construct library ships the lab's full collection of 94 constructs. Item wording,
56
  reverse-scoring keys, subscale grouping, and citations were reviewed against the source
57
- publications in August 2026: 81 constructs are marked verified and carry the reviewer
58
- and review date. The other 13 stay flagged in the interface and each records why - an
59
  open wording question, a proposed correction that disagreed with the cited paper, an
60
  unresolved item-ordering question, or no reachable source document. See
61
  `docs/specs/0007-construct-library-verification-pass.md`.
 
54
  storage is ephemeral and the instance may reset.
55
  - The construct library ships the lab's full collection of 94 constructs. Item wording,
56
  reverse-scoring keys, subscale grouping, and citations were reviewed against the source
57
+ publications in August 2026: 83 constructs are marked verified and carry the reviewer
58
+ and review date. The other 11 stay flagged in the interface and each records why - an
59
  open wording question, a proposed correction that disagreed with the cited paper, an
60
  unresolved item-ordering question, or no reachable source document. See
61
  `docs/specs/0007-construct-library-verification-pass.md`.
backend/tests/test_construct_library_versions.py CHANGED
@@ -175,8 +175,8 @@ def test_review_applied_expected_shape():
175
  by_status.setdefault(c["verification_status"], []).append(c)
176
 
177
  assert len(by_status["archived"]) == 21, "superseded v1 files"
178
- assert len(by_status["verified"]) == 81
179
- assert len(by_status["needs_verification"]) == 13
180
 
181
  live = [c for c in constructs if c["verification_status"] != "archived"]
182
  assert len({c["construct_id"] for c in live}) == 94, "one live version per construct"
@@ -199,7 +199,6 @@ def test_review_applied_expected_shape():
199
  # PI decision: restoring the shared K10 stem onto each item
200
  "k10",
201
  # reviewer's correction contradicts the cited publication
202
- "mfq_fairness",
203
  "team_psychological_safety_scale",
204
  # reviewer reported an item-ORDER problem that is not applied
205
  "cbi_work_related_burnout",
@@ -207,7 +206,6 @@ def test_review_applied_expected_shape():
207
  # no reachable source on record, so "verified" cannot be claimed
208
  "bas_2",
209
  "cage_questionnaire",
210
- "mfq_care",
211
  ]
212
  )
213
  for c in by_status["needs_verification"]:
 
175
  by_status.setdefault(c["verification_status"], []).append(c)
176
 
177
  assert len(by_status["archived"]) == 21, "superseded v1 files"
178
+ assert len(by_status["verified"]) == 83
179
+ assert len(by_status["needs_verification"]) == 11
180
 
181
  live = [c for c in constructs if c["verification_status"] != "archived"]
182
  assert len({c["construct_id"] for c in live}) == 94, "one live version per construct"
 
199
  # PI decision: restoring the shared K10 stem onto each item
200
  "k10",
201
  # reviewer's correction contradicts the cited publication
 
202
  "team_psychological_safety_scale",
203
  # reviewer reported an item-ORDER problem that is not applied
204
  "cbi_work_related_burnout",
 
206
  # no reachable source on record, so "verified" cannot be claimed
207
  "bas_2",
208
  "cage_questionnaire",
 
209
  ]
210
  )
211
  for c in by_status["needs_verification"]:
docs/specs/0007-construct-library-verification-pass.md CHANGED
@@ -16,8 +16,8 @@ loadings computed from mis-flagged items are wrong in a way nothing surfaces.
16
  Noor Skhiri reviewed all 525 items (returned 2026-08-25), checking wording, reverse
17
  keying, subscale grouping, and citation for each. This spec applies her review.
18
 
19
- Two of her findings raise questions that are the PI's to answer, so they are
20
- deliberately NOT applied here (see Non-goals).
21
 
22
  ## Contract
23
 
@@ -44,7 +44,7 @@ append-only means old versions remain resolvable for runs that already used them
44
  Metadata-level changes do NOT feed `item_hash` and are therefore applied in place on
45
  the existing version:
46
 
47
- - `verification_status` promoted `needs_verification -> verified` for 81 constructs.
48
  - Citation and `source_url` repairs (dead links replaced with the URLs the reviewer
49
  supplied, DOIs she supplied added).
50
  - A `review:` provenance block on every construct recording reviewer, review date, and
@@ -91,7 +91,7 @@ construct reproduce exactly as before, because v1 rows are never mutated.
91
 
92
  ## Non-goals
93
 
94
- 13 constructs keep `verification_status: needs_verification`, each with the reason
95
  recorded in its `review.notes`.
96
 
97
  **Two of the reviewer's wording corrections are NOT applied, because each disagrees with
@@ -99,7 +99,9 @@ the publication its own construct cites.** Both were checked against the source:
99
 
100
  - `mfq_fairness` item 3: she proposed "treated differently from others"; the published
101
  MFQ30 reads "treated differently **than** others", which is what the library already
102
- had.
 
 
103
  - `team_psychological_safety_scale` item 4: she proposed "It is safe to take a risk **in**
104
  this team", sourced from a third-party questionnaire (novopsych TPS-7); Edmondson
105
  (1999), the cited paper and the recorded `source_url`, reads "on this team", which is
@@ -117,10 +119,12 @@ feeds `item_hash` and decides what each `sim_item_N` export column refers to, so
117
  reordering is a scoring-visible change that needs a decision rather than a silent fix.
118
  Their reverse-scoring corrections ARE applied.
119
 
120
- **Three constructs have no reachable source on record** (`bas_2`, `cage_questionnaire`,
121
- `mfq_care`; `mfq_fairness` too). The reviewer checked what she could and flagged the
122
- missing links; "verified verbatim against the original publication" cannot honestly be
123
- claimed without one, so they stay unverified until a working source is on file.
 
 
124
 
125
  **Two findings are left pending an explicit PI decision:**
126
 
@@ -151,7 +155,7 @@ similarities plus flags; `adjustment_strategy` remains a recorded parameter).
151
  updates the existing row.
152
  - `test_sync_still_refuses_item_change_under_same_version` - the append-only guard is
153
  intact.
154
- - `test_review_applied_expected_shape` - 21 v2 files, 81 verified, 13
155
  needs_verification, 96 reverse flags, and every unverified construct carries a recorded
156
  reason.
157
  - `test_superseded_files_keep_their_original_items` - compares every tracked construct
 
16
  Noor Skhiri reviewed all 525 items (returned 2026-08-25), checking wording, reverse
17
  keying, subscale grouping, and citation for each. This spec applies her review.
18
 
19
+ Some of her findings are not applied here: two need a PI decision, and several turned
20
+ out to be version differences or gaps in the review sheet we sent her (see Non-goals).
21
 
22
  ## Contract
23
 
 
44
  Metadata-level changes do NOT feed `item_hash` and are therefore applied in place on
45
  the existing version:
46
 
47
+ - `verification_status` promoted `needs_verification -> verified` for 83 constructs.
48
  - Citation and `source_url` repairs (dead links replaced with the URLs the reviewer
49
  supplied, DOIs she supplied added).
50
  - A `review:` provenance block on every construct recording reviewer, review date, and
 
91
 
92
  ## Non-goals
93
 
94
+ 11 constructs keep `verification_status: needs_verification`, each with the reason
95
  recorded in its `review.notes`.
96
 
97
  **Two of the reviewer's wording corrections are NOT applied, because each disagrees with
 
99
 
100
  - `mfq_fairness` item 3: she proposed "treated differently from others"; the published
101
  MFQ30 reads "treated differently **than** others", which is what the library already
102
+ had. This one is resolved: the MFQ30 is now recorded as the construct's `source_url`
103
+ (the review sheet shipped without one), all four items check out verbatim against it,
104
+ and the construct is verified.
105
  - `team_psychological_safety_scale` item 4: she proposed "It is safe to take a risk **in**
106
  this team", sourced from a third-party questionnaire (novopsych TPS-7); Edmondson
107
  (1999), the cited paper and the recorded `source_url`, reads "on this team", which is
 
119
  reordering is a scoring-visible change that needs a decision rather than a silent fix.
120
  Their reverse-scoring corrections ARE applied.
121
 
122
+ **Two constructs have no reachable source on record** (`bas_2`, whose recorded URL 404s,
123
+ and `cage_questionnaire`, whose URL returns 403). "Verified verbatim against the original
124
+ publication" cannot honestly be claimed without one, so they stay unverified until a
125
+ working source is on file. `mfq_care` and `mfq_fairness` were in this group because the
126
+ review sheet shipped with an EMPTY `source_url` for both - our omission, not a missing
127
+ document. The MFQ30 is now recorded for each and their items confirmed verbatim.
128
 
129
  **Two findings are left pending an explicit PI decision:**
130
 
 
155
  updates the existing row.
156
  - `test_sync_still_refuses_item_change_under_same_version` - the append-only guard is
157
  intact.
158
+ - `test_review_applied_expected_shape` - 21 v2 files, 83 verified, 11
159
  needs_verification, 96 reverse flags, and every unverified construct carries a recorded
160
  reason.
161
  - `test_superseded_files_keep_their_original_items` - compares every tracked construct
packages/construct_library/apply_review.py CHANGED
@@ -52,7 +52,6 @@ PENDING = {
52
  "k10",
53
  # Reviewer's correction disagrees with the cited publication (see below).
54
  "team_psychological_safety_scale",
55
- "mfq_fairness",
56
  # Reviewer reported an item-ORDER problem, which is not applied here. Order
57
  # feeds item_hash and decides what sim_item_N means in an export, so it is
58
  # not a cosmetic change to make without a decision.
@@ -62,7 +61,6 @@ PENDING = {
62
  # publication" cannot honestly be claimed.
63
  "bas_2",
64
  "cage_questionnaire",
65
- "mfq_care",
66
  }
67
  PENDING_NOTE = {
68
  "k10": (
@@ -76,11 +74,6 @@ PENDING_NOTE = {
76
  "safe to take a risk on this team' - the wording already stored here. Kept as "
77
  "published; the two sources disagree and the citation should decide."
78
  ),
79
- "mfq_fairness": (
80
- "Reviewer proposed 'treated differently from others'. The published MFQ30 reads "
81
- "'treated differently than others' - the wording already stored here. Kept as "
82
- "published. No source_url on file yet."
83
- ),
84
  "rses": (
85
  "Reviewer maps stored items 1,2,3,6,7,9,10 to source item numbers 7,10,2,9,1,3,6: "
86
  "the item ORDER does not match the source. Reverse-scoring corrections are applied; "
@@ -103,7 +96,6 @@ PENDING_NOTE = {
103
  "reviewer's wording correction ('ought to' -> 'should') is applied; a working "
104
  "source link is still needed before this can be called verified."
105
  ),
106
- "mfq_care": "Citation is correct; no source_url on file yet, so wording is unconfirmed.",
107
  }
108
  IPIP_NOTE = (
109
  "Reviewer confirms wording matches the source apart from the leading 'I' that CCR "
@@ -176,6 +168,10 @@ SOURCE_URL_FIX = {
176
  "dirty_dozen_narcissism": "https://psycnet.apa.org/fulltext/2010-10892-021.pdf",
177
  "dirty_dozen_psychopathy": "https://psycnet.apa.org/fulltext/2010-10892-021.pdf",
178
  "lot_r": "https://psycnet.apa.org/fulltext/1995-07978-001.pdf",
 
 
 
 
179
  "collectivism_horizontal": "https://psycnet.apa.org/fulltext/1997-38342-009.pdf",
180
  "individualism_horizontal": "https://psycnet.apa.org/fulltext/1997-38342-009.pdf",
181
  }
@@ -211,6 +207,14 @@ QUESTIONNAIRE_FIX = {
211
  REVIEW_NOTE = {
212
  "lot_r": "The scale's 4 filler items are correctly excluded from this construct; they are "
213
  "not scored in the source.",
 
 
 
 
 
 
 
 
214
  }
215
 
216
 
 
52
  "k10",
53
  # Reviewer's correction disagrees with the cited publication (see below).
54
  "team_psychological_safety_scale",
 
55
  # Reviewer reported an item-ORDER problem, which is not applied here. Order
56
  # feeds item_hash and decides what sim_item_N means in an export, so it is
57
  # not a cosmetic change to make without a decision.
 
61
  # publication" cannot honestly be claimed.
62
  "bas_2",
63
  "cage_questionnaire",
 
64
  }
65
  PENDING_NOTE = {
66
  "k10": (
 
74
  "safe to take a risk on this team' - the wording already stored here. Kept as "
75
  "published; the two sources disagree and the citation should decide."
76
  ),
 
 
 
 
 
77
  "rses": (
78
  "Reviewer maps stored items 1,2,3,6,7,9,10 to source item numbers 7,10,2,9,1,3,6: "
79
  "the item ORDER does not match the source. Reverse-scoring corrections are applied; "
 
96
  "reviewer's wording correction ('ought to' -> 'should') is applied; a working "
97
  "source link is still needed before this can be called verified."
98
  ),
 
99
  }
100
  IPIP_NOTE = (
101
  "Reviewer confirms wording matches the source apart from the leading 'I' that CCR "
 
168
  "dirty_dozen_narcissism": "https://psycnet.apa.org/fulltext/2010-10892-021.pdf",
169
  "dirty_dozen_psychopathy": "https://psycnet.apa.org/fulltext/2010-10892-021.pdf",
170
  "lot_r": "https://psycnet.apa.org/fulltext/1995-07978-001.pdf",
171
+ # The sheet went out with no source_url for these two, so the reviewer had
172
+ # nothing to check against. Added afterwards and confirmed item by item.
173
+ "mfq_care": "https://moralfoundations.org/wp-content/uploads/files/MFQ30.doc",
174
+ "mfq_fairness": "https://moralfoundations.org/wp-content/uploads/files/MFQ30.doc",
175
  "collectivism_horizontal": "https://psycnet.apa.org/fulltext/1997-38342-009.pdf",
176
  "individualism_horizontal": "https://psycnet.apa.org/fulltext/1997-38342-009.pdf",
177
  }
 
207
  REVIEW_NOTE = {
208
  "lot_r": "The scale's 4 filler items are correctly excluded from this construct; they are "
209
  "not scored in the source.",
210
+ "mfq_care": "Reviewer flagged the missing source_url (the sheet shipped without one for this "
211
+ "construct). Source added and all 4 items confirmed verbatim against the "
212
+ "published MFQ30. The construct uses a subset of the foundation's items, which "
213
+ "the reviewer confirmed as correctly grouped.",
214
+ "mfq_fairness": "Reviewer flagged the missing source_url (the sheet shipped without one) and "
215
+ "proposed 'treated differently from others'. Source added: the published "
216
+ "MFQ30 reads 'treated differently than others', which is the wording already "
217
+ "stored here, so it is kept and all 4 items are confirmed verbatim.",
218
  }
219
 
220
 
packages/construct_library/constructs/mfq_care.yaml CHANGED
@@ -7,12 +7,15 @@ category: moral-foundations
7
  description: Concern with suffering, compassion, and protection of the vulnerable (MFQ Care/Harm).
8
  citation: Graham, J., Nosek, B. A., Haidt, J., Iyer, R., Koleva, S., & Ditto, P. H. (2011). Mapping the
9
  moral domain. JPSP, 101(2).
10
- verification_status: needs_verification
11
  review:
12
  reviewer: Noor Skhiri
13
  date: '2026-08-25'
14
- outcome: pending_pi_decision
15
- notes: Citation is correct; no source_url on file yet, so wording is unconfirmed.
 
 
 
16
  items:
17
  - item_id: care_1
18
  text: Compassion for those who are suffering is the most crucial virtue.
 
7
  description: Concern with suffering, compassion, and protection of the vulnerable (MFQ Care/Harm).
8
  citation: Graham, J., Nosek, B. A., Haidt, J., Iyer, R., Koleva, S., & Ditto, P. H. (2011). Mapping the
9
  moral domain. JPSP, 101(2).
10
+ verification_status: verified
11
  review:
12
  reviewer: Noor Skhiri
13
  date: '2026-08-25'
14
+ outcome: verified
15
+ notes: Reviewer flagged the missing source_url (the sheet shipped without one for this construct). Source
16
+ added and all 4 items confirmed verbatim against the published MFQ30. The construct uses a subset
17
+ of the foundation's items, which the reviewer confirmed as correctly grouped.
18
+ source_url: https://moralfoundations.org/wp-content/uploads/files/MFQ30.doc
19
  items:
20
  - item_id: care_1
21
  text: Compassion for those who are suffering is the most crucial virtue.
packages/construct_library/constructs/mfq_fairness.yaml CHANGED
@@ -7,13 +7,15 @@ category: moral-foundations
7
  description: Concern with justice, rights, and equal treatment (MFQ Fairness/Cheating).
8
  citation: Graham, J., Nosek, B. A., Haidt, J., Iyer, R., Koleva, S., & Ditto, P. H. (2011). Mapping the
9
  moral domain. JPSP, 101(2).
10
- verification_status: needs_verification
11
  review:
12
  reviewer: Noor Skhiri
13
  date: '2026-08-25'
14
- outcome: pending_pi_decision
15
- notes: Reviewer proposed 'treated differently from others'. The published MFQ30 reads 'treated differently
16
- than others' - the wording already stored here. Kept as published. No source_url on file yet.
 
 
17
  items:
18
  - item_id: fair_1
19
  text: Justice is the most important requirement for a society.
 
7
  description: Concern with justice, rights, and equal treatment (MFQ Fairness/Cheating).
8
  citation: Graham, J., Nosek, B. A., Haidt, J., Iyer, R., Koleva, S., & Ditto, P. H. (2011). Mapping the
9
  moral domain. JPSP, 101(2).
10
+ verification_status: verified
11
  review:
12
  reviewer: Noor Skhiri
13
  date: '2026-08-25'
14
+ outcome: verified
15
+ notes: 'Reviewer flagged the missing source_url (the sheet shipped without one) and proposed ''treated
16
+ differently from others''. Source added: the published MFQ30 reads ''treated differently than others'',
17
+ which is the wording already stored here, so it is kept and all 4 items are confirmed verbatim.'
18
+ source_url: https://moralfoundations.org/wp-content/uploads/files/MFQ30.doc
19
  items:
20
  - item_id: fair_1
21
  text: Justice is the most important requirement for a society.