Filed by the repo:hotcrm PM seat from a measurement reported in PR #1297 (#1295). It is the residual half of that card, deliberately left outside its fence and reported rather than swept in.
The gap
#1295 routed test/helpers/hook-harness.ts's makeCtx through the engine's real wrapper (wrapDeclarativeHook), so a hook handler now receives the flat-record Proxy production hands it instead of a plain object. That closed the blind spot for every call site that goes through makeCtx.
39 call sites across 14 test files do not. They build a hook ctx inline:
const ctx = { event: 'beforeInsert', input, user: undefined, api: harness.api };
so input is a plain object and those assertions keep exactly the under-approximation #1295 removed.
| file |
sites |
test/hooks-runtime.test.ts |
18 |
test/flow-scheduled.test.ts |
2 |
test/forecast-period-boundary.test.ts |
2 |
test/knowledge-deflection.test.ts |
2 |
test/knowledge-feedback.test.ts |
2 |
test/ownership-model.test.ts |
2 |
action-sandbox · demo-staffing · forecast-period-end-boundary · priority-rank-parity · quote-accepted-lookups · quote-accepted-payment-terms · territory-seed-coverage |
1 each |
(test/case-assignment.test.ts's 4 were converted in PR #1297 — the two the card named plus their handler calls.)
Why it is worth doing rather than noting
This is the shape that produced #1133: fifteen delete statements were silent no-ops in production while the tests asserting them passed, because a plain object honours delete and the engine's Proxy does not. Those tests were not merely failing to catch the defect — they were certifying the opposite of production for as long as it existed.
⚠️ test/hooks-runtime.test.ts alone holds 18 of the 39, and it is a hooks-runtime file — the highest-density place in the repo for exactly the class of defect this shape hides.
The failure also generalises past delete: ownKeys ordering, getOwnPropertyDescriptor, has on an absent key, and the non-enumerable reserved keys all diverge between the two shapes, with the same green tests either way.
Direction
Most of these files carry a single local ctxFor-style builder, so the conversion is roughly one line per file — point the builder at makeCtx (or at the exported engineFlatInput) instead of an object literal.
⛔ Every assertion that changes verdict is a finding to READ, not noise to suppress. #1295 changed no verdict because PR #1294 had already retired the last live delete; these 39 may not be so lucky, and a red here is the instrument finally telling the truth. ⛔ Never weaken, skip or delete a test to get green — if a red is a genuine defect outside this card's scope, stop and report it.
⚠️ Note the one disclosed divergence in the new harness before relying on it: id is hoisted onto the wrapper by copy, so a record carrying id has it in both places and Object.keys lists it where a real per-row update dispatch would not. Approximate in the enumerable direction only — if a converted assertion trips on exactly that, it is the harness, not the hook.
Acceptance
- All 39 sites build their ctx through the shared helper, or each exception is named with a measured reason.
- ⚠️ A pin, or an existing gate extended, that makes a new inline plain-object ctx visible — otherwise the 40th call site re-opens this silently.
test/hook-input-shape.test.ts is the natural home.
Refs #1295 · PR #1297 · #1133 · PR #1294 · objectstack#12277
Filed by the
repo:hotcrmPM seat from a measurement reported in PR #1297 (#1295). It is the residual half of that card, deliberately left outside its fence and reported rather than swept in.The gap
#1295 routed
test/helpers/hook-harness.ts'smakeCtxthrough the engine's real wrapper (wrapDeclarativeHook), so a hook handler now receives the flat-record Proxy production hands it instead of a plain object. That closed the blind spot for every call site that goes throughmakeCtx.39 call sites across 14 test files do not. They build a hook ctx inline:
so
inputis a plain object and those assertions keep exactly the under-approximation #1295 removed.test/hooks-runtime.test.tstest/flow-scheduled.test.tstest/forecast-period-boundary.test.tstest/knowledge-deflection.test.tstest/knowledge-feedback.test.tstest/ownership-model.test.tsaction-sandbox·demo-staffing·forecast-period-end-boundary·priority-rank-parity·quote-accepted-lookups·quote-accepted-payment-terms·territory-seed-coverage(
test/case-assignment.test.ts's 4 were converted in PR #1297 — the two the card named plus their handler calls.)Why it is worth doing rather than noting
This is the shape that produced #1133: fifteen
deletestatements were silent no-ops in production while the tests asserting them passed, because a plain object honoursdeleteand the engine's Proxy does not. Those tests were not merely failing to catch the defect — they were certifying the opposite of production for as long as it existed.test/hooks-runtime.test.tsalone holds 18 of the 39, and it is a hooks-runtime file — the highest-density place in the repo for exactly the class of defect this shape hides.The failure also generalises past
delete:ownKeysordering,getOwnPropertyDescriptor,hason an absent key, and the non-enumerable reserved keys all diverge between the two shapes, with the same green tests either way.Direction
Most of these files carry a single local
ctxFor-style builder, so the conversion is roughly one line per file — point the builder atmakeCtx(or at the exportedengineFlatInput) instead of an object literal.⛔ Every assertion that changes verdict is a finding to READ, not noise to suppress. #1295 changed no verdict because PR #1294 had already retired the last live
delete; these 39 may not be so lucky, and a red here is the instrument finally telling the truth. ⛔ Never weaken, skip or delete a test to get green — if a red is a genuine defect outside this card's scope, stop and report it.idis hoisted onto the wrapper by copy, so a record carryingidhas it in both places andObject.keyslists it where a real per-row update dispatch would not. Approximate in the enumerable direction only — if a converted assertion trips on exactly that, it is the harness, not the hook.Acceptance
test/hook-input-shape.test.tsis the natural home.Refs #1295 · PR #1297 · #1133 · PR #1294 · objectstack#12277