Repository navigation
[GA close-out B2] Engine-behaviour GA probes: #698, #1141, #691, #701, #520, #779 #1153
Description
Split from #1150 (GA close-out sweep) — the non-UI engine-behaviour half of groups 3 and 4, plus two cards handed over from #1151. Measurement only; no product code changes, no commits, no push, no PR.
Repo is on @objectstack/* 17.0.0 GA (#1146 / PR #1147), commit d4ddee0. Every card below was last measured on an rc build. Use port 4002 (HOTCRM_PORT=4002) — sibling agents hold 4001 and 4003.
Cards
Confirmation probes (#1150 group 3) — close if green
- [17.0-rc][疑似平台] crm_case 自动编号计数器落后于既有 case_number:REST 建单连续 409,每次失败还烧掉一个号(实测重试 25 次才成功) #698 —
crm_caseautonumber counter lags the existingcase_number: REST creates 409 continuously and each failure burns a number (measured: 25 retries before success). [GA close-out sweep] Apply the #1106 verdicts, close the verified-fixed rc-era platform cards, GA-retest the 8 likely-live ones #1150 scopes this card to its residual halves only: the burn-on-failure behaviour, and the silent duplicate-numbering mode found on 2026-08-05. Read the comments for what was already settled — do not re-litigate the closed half. - A misspelled top-level stack key is silently stripped, not rejected — the artifact just loses it #1141 — remaining half: an unknown top-level stack key is named but still not rejected. The naming half landed; the rejection half is what you are measuring.
GA-retests (#1150 group 4)
- [17.0-rc][疑似平台] 缺少必填的 master-detail 父记录时返回 403 PERMISSION_DENIED,而非其它必填字段一致的 400 VALIDATION_FAILED #691 — a missing required master-detail parent returns
403 PERMISSION_DENIEDwhere every other missing required field returns400 VALIDATION_FAILED. Measure both branches so the inconsistency is shown, not asserted. - [17.0-rc][疑似平台] 记录变更流会因自己的写入重入自身 —— 阻止死循环的是引擎的 loop-breaker,而不是流作者写的 start condition #701 — record-change flows re-enter themselves on their own writes; what actually stops the loop is the engine's loop-breaker, not the flow author's start condition. The interesting reading is which mechanism halts it on GA, so design the probe to tell those two apart — a flow that merely terminates does not distinguish them.
⚠️ Handed over from #1151 — these were about to fall through the sweep
#1151 was asked to direct-close these two on recorded evidence and correctly refused, because the recorded readings do not establish a fix. They appear in no other probe set, so they are yours. Read #1151's refusal comment on each card first — it names precisely what is missing.
- [17.0-rc][疑似平台] datetime 字段的时间窗过滤返回空集(客服仪表盘全空) #520 — datetime-field time-window filtering returns an empty set (service dashboard renders blank). The rc.6 reading on-card is a driver-level probe that disclaims this card's dashboard scope in its own words, and both recorded readings gate closure on repo-side work that has not been done. The probe owed here is the dashboard path, not the driver primitive.
- 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779 — on the bulk-write path (
multi: true)ctx.previousis always empty, so 15 hooks that readprevioussilently no-op there; a knowledge article can be bulk-written to "published but never reviewed". The rc.6 reading is static, states its conclusion conditionally, and says to re-run the repro before closing.⚠️ It also surfaced a new per-row dispatch ceiling that rejects bulk writes — measure whether that ceiling now masks the original defect, or replaces it with a different one. Those are different outcomes and only one of them justifies a close.- Label note: 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779 wears a stale
pm:blockedwhose blocker (objectstack#5574) has landed. Drop it in whatever label write your outcome produces — close, or leave-open-with-reading. Do not leave the card wearing a blocker that no longer exists.
- Label note: 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779 wears a stale
What to do per card
- Read the full body and every comment — original probe, exact commands, later re-measurements, PM triage that narrowed the card, and ([17.0-rc][疑似平台] datetime 字段的时间窗过滤返回空集(客服仪表盘全空) #520 / 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779) [GA close-out A] Bookkeeping: record the #1106 verdicts as already-applied, direct-close the 8 verified-fixed rc-era cards #1151's refusal comment.
- Re-run the card's own reproduction on 17.0.0 GA. Before trusting a green, ask what the probe would print if the defect were still present. A probe that structurally cannot fail proves nothing — this repo has a documented case (Nine object files import
F, Pfrom @objectstack/spec and never use them — three of them above the license header #1091) of exactly that sitting in the backlog for a week. If a card's original repro has that shape, say so and build one that can fail. - Non-reproducer ⇒ close with the reading (version, probe, result). Drop
pm:blockedin the same label write where present ([17.0-rc][疑似平台] crm_case 自动编号计数器落后于既有 case_number:REST 建单连续 409,每次失败还烧掉一个号(实测重试 25 次才成功) #698, 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779). A label update replaces the whole set — pass the full desired list. - Survivor ⇒ leave open, post the GA reading, then file or refresh an objectstack mirror and nominate it on [Epic] v17 bug focus — Seat A: platform bugs (objectstack) objectstack#8667.
- Partial ⇒ for [17.0-rc][疑似平台] crm_case 自动编号计数器落后于既有 case_number:REST 建单连续 409,每次失败还烧掉一个号(实测重试 25 次才成功) #698 and A misspelled top-level stack key is silently stripped, not rejected — the artifact just loses it #1141 especially, the expected outcome is "one half fixed, one half live". Report halves separately; close only if every half in scope is green.
⛔ Boundaries
- You nominate; you do not label. ⛔ Do NOT apply
target:v17, do not edit the #8667 first-batch list. Nominations are comments naming the card and the evidence. #8667: "the PM nominates … the maintainer approves by labeling"; [GA close-out sweep] Apply the #1106 verdicts, close the verified-fixed rc-era platform cards, GA-retest the 8 likely-live ones #1150: "Seat A decides nothing". - #8667 scopes hotcrm out. Nothing from this card enters that theme except the mirror nominations above.
- No fixes and no workarounds. Root cause belongs in the mirror, not in a patch here.
⚠️ Do not trust "verified fixed" claims in this repo's account-book. Three separate "nobody executed this" premises have already been falsified during this sweep. Measure.
Worktree
Dev agents are working hotcrm concurrently — the shared checkout gets its HEAD moved under you. git worktree add ../hotcrm-issue-1153 -b claude/issue-1153-ga-engine-probes && cd ../hotcrm-issue-1153 && pnpm install. The pnpm store is pre-warmed (~1m43s). Existing REST-probe patterns worth reading first: e2e/fixtures.ts, e2e/opportunity-lifecycle.spec.ts, and test/helpers/ (hook-harness.ts, flow-harness.ts, action-sandbox.ts).
Acceptance
- All 6 cards measured on 17.0.0 GA, each with a posted reading naming version + probe + result.
- Non-reproducers closed; survivors carry a mirror + a nomination comment (no labels).
- A summary comment on [GA close-out sweep] Apply the #1106 verdicts, close the verified-fixed rc-era platform cards, GA-retest the 8 likely-live ones #1150.
- Probe scaffolding deleted;
git statusclean; no product code changed.
Activity
[-][GA close-out B2] Engine-behaviour GA probes: #698, #1141, #691, #701[/-][+][GA close-out B2] Engine-behaviour GA probes: #698, #1141, #691, #701, #520, #779[/+]hotlong commentedon Aug 14, 2026
Claim: PM loop round 2
Session:
session_01XAK3brMLjd4ykF4QAhFnuoBranch:
claude/issue-1153-ga-engine-probesWorktree:
hotcrm-issue-1153Domain:
repo:hotcrm(parent #1150, engine half of groups 3 + 4, plus #520 / #779 handed over from #1151)File surface: throwaway probe scaffolding only, deleted before reporting; no product source (stop on breach; explain in the report)
Container & model:
L,mode:subagent,model: opusSerial constraints cleared: port 4002 reserved for this claim (siblings hold 4001 on #1152 and 4003 on #1154). Card surface #698 #1141 #691 #701 #520 #779 is disjoint from #1152 and #1154; #1151 is closed and released #520 / #779 to this card explicitly. No same-file predecessor PRs — no product files are edited.
Scope grew after the card was filed: #520 and #779 were added when #1151 refused to close them on recorded evidence and no other probe set covered them.
Generated by Claude Code
hotlong commentedon Aug 14, 2026
Result — all 6 cards measured on 17.0.0 GA · 2 closed, 4 survive
--strictcannot catch it either403 PERMISSION_DENIEDfields[],[Security]prefix, guard ordering)pm:blockeddroppedBoth "one half fixed, one half live" predictions in this card's item 5 were correct. #698 and #1141 came back exactly that way, and #691 turned out to be a third instance of the same shape that the card did not predict.
On the two handed over from #1151
last_30_days -> {30_days_ago}/{today}mapping, so no browser was needed). The fourth was repo-side work outside this mandate and is now Restore the Service dashboard'sdateRangeand relax the #546 CI guard — both upstream preconditions have landed and the window is measurably correct on 17.0.0 GA #1157 rather than a reason to hold a platform card open.ERR_BULK_PER_ROW_HOOK_LIMITand 0 rows written. So it neither masks the defect (per-row dispatch demonstrably runs at the largest accepted batch) nor replaces it (loud and atomic is the opposite of this card's silent no-op). That is the only outcome of the two that justified a close, and it is the one that was measured.Probes that could not fail were replaced
Three of the six original repros had that shape and were rebuilt:
$gtehalf (silently unfiltered, not empty) is visible at all.Two probes caught their own defects mid-run and are worth recording: the first #698 burn probe planted its collision against the
__global__sequence and reported INCONCLUSIVE rather than green; the first #779 run reportedregistered:0, skipped:1from the hook binder and aborted rather than measuring an engine with no hook bound.Report
{ "issue": 1153, "status": "done", "branch": "claude/issue-1153-ga-engine-probes", "pr": null, "premise_still_valid": true, "summary": "All six cards re-measured live on @objectstack/* 17.0.0 GA (hotcrm d4ddee0, dev server on port 4002, fresh seeded DB). #520 and #779 did not reproduce and were closed with full readings; #779's label write dropped the stale pm:blocked. #698, #1141 and #691 each came back one-half-fixed / one-half-live, and #701 reproduces outright on both named flows; all four stay open with GA readings, fresh objectstack mirrors (#8686/#8687/#8688/#8689) and one nomination comment on objectstack#8667. No target:v17 applied and the #8667 first-batch list untouched. No product code changed, no commits, no PR; scaffolding deleted and git status clean.", "tests": "Measurement-only card — no build/test gates apply. Probes, all foreground: (698) fresh-DB REST creates minted CASE-00001..4 duplicating seeds, duplicate case_number values [[CASE-00001,2],...]; two sequence rows __global__=38 and org_mssymr19xzd645gv=6 under UNIQUE INDEX (COALESCE(organization_id,'__global__'), case_number); burn half not reproduced - planted band CASE-00012..20, ONE create returned 201 CASE-00021 counter 11->21, rejected create left counter 22->22. (1141) safeParse accepts+drops 4 unknown top-level keys with a valid-stack positive control passing; validate exit 0 baseline and 0 with bogus keys, --strict exit 1 in BOTH (baseline control), warning sets byte-identical 88 vs 88. (691) six REST branches one session: master omitted 422 MISSING_REQUIRED_FIELD no fields[]; master present+unresolvable 400 VALIDATION_FAILED fields[reference_not_found]; same object master supplied + scalar omitted 400 VALIDATION_FAILED fields[2]. (701) case v5_h-3H_CbMj6jag fired to status=escalated then 1 loop-breaker WARN naming that id, guard terms status!='escalated'->false and escalated_date==null->false; opportunity RnrCSh-5GvgPkzSM same shape; 3 more WARNs unprompted during demo_bootstrap. (520) dataset/query vs SQLite truth: none 51/51, $gte 37/37, $lte 1/1, window 37/37, bare-date 1/1; 7 dashboard widgets windowed, 0 blank, 0 disagreeing; 21/21 widget-preset combinations via {N_days_ago}/{today}. (779) real engine + driver-memory + shipped knowledge_article.hook bound via bindHooksToEngine (asserted registered:2 skipped:0 before measuring): per-row input.id and previous bound on multi:true, bulk edit refreshes last_reviewed_at, bulk null-write leaves 0 of 2 published rows empty, single-row positive control healthy; ceiling boundary 10000 -> OK with 10000/10000 stamped, 10001 -> ERR_BULK_PER_ROW_HOOK_LIMIT with 0 rows written. Cleanup: dev server killed by recorded PID only (sibling on 4003 verified still 200), all scaffolding deleted, git status clean, objectstack.config.ts hash unchanged at bd8cb34b2d9c2bbf342d44ed94c0a2ec8e626184, git diff origin/main empty.", "open_questions": [ { "question": "#698 is a SURVIVOR but I dropped its stale pm:blocked. This card ties that drop to the non-reproducer branch ('Non-reproducer => close with the reading, dropping pm:blocked where present (#698, #779)'), and grants 'whatever the outcome' only to #779. Was extending it to #698 correct?", "options": [ "Keep it dropped — objectstack#5495 is closed as completed via merged PR objectstack#6932, so the card was blocked on a blocker that no longer exists, which is the instruction's own stated rationale", "Re-apply pm:blocked — the letter of the instruction scoped the drop to a close, and #1151 set the precedent of deliberately leaving the label on an open card" ], "recommendation": "Keep it dropped. The blocker is verifiably merged and a survivor that still needs platform work is exactly the card that must be dispatchable. Flagged in the card comment too, so it is a one-edit reversal if the PM disagrees." }, { "question": "#520 was closed without a browser opening the dashboard, because the console's own preset->macro mapping table made the last unverified link measurable from the API side. Is that substitution acceptable, or should a browser pass on #1154 confirm it before the close stands?", "options": [ "Close stands — 21/21 widget-preset combinations match ground truth through the exact spelling the shipped console emits, and the console mapping was read out of the shipped bundle rather than assumed", "Reopen until #1154 (or a follow-up) renders the dashboard with a picker present" ], "recommendation": "Close stands. What remains untested is the console's rendering, not the platform defect this card is about — and #1157 already carries a browser-verify step as part of restoring the picker, so the visual confirmation happens there with something to actually look at." } ], "out_of_scope_findings": [ "filed as #1157: restore the Service dashboard's dateRange and relax the #546 CI guard — both upstream preconditions (objectstack#3912, #3777) have landed and the window is measurably correct on GA; unassigned, includes the daily_case_volume re-check and a browser-verify step", "filed as objectstack-ai/objectstack#8690: an unparseable date comparand on a datetime filter is passed through and compares false — HTTP 200, zero rows, no diagnostic — while an unknown {placeholder} on the same request is rejected 400 FILTER_TOKEN_UNKNOWN; same blank-screen symptom as #520 by a different cause, filed rather than folded in so #520's close stays honest" ] }Boundaries observed
No
target:v17applied to anything; the #8667 first-batch list was not edited; nominations are comments. No product code changed —objectstack.config.tsverified byte-identical (bd8cb34b…),git diff origin/mainempty,git statusclean, zero commits on the branch. The twovalidatecomparison runs used copies of the config at throwaway paths, so the real file was never edited. No fixes and no workarounds anywhere.Generated by Claude Code
Generated by Claude Code
hotlong commentedon Aug 14, 2026
PM review — ACCEPT
Reviewed against GitHub, not against the report. Session
session_01XAK3brMLjd4ykF4QAhFnuo.Verified independently: #520 and #779 no longer appear in the open
upstream:objectstackset — both closed. #698, #1141, #691, #701 open; #698 carries nopm:blocked. objectstack#8686, #8687, #8688, #8689 and #8690 all exist carryingbugonly — notarget:v17on any of the five, first-batch list untouched. hotcrm#1157 filed. Worktree removed, scaffolding gone,git statusclean,objectstack.config.tshash unchanged.Answers to the two questions
Q1 — #698 is a survivor and you dropped its
pm:blocked. Correct? Yes. Keep it dropped, and my instruction was the thing that was too narrow, not your reading of it.pm:blockedis not decoration; it asserts "this card is waiting on an unlanded upstream change". objectstack#5495 is closed as completed via merged PR #6932, so that assertion is false, and a false state label is worse than a missing one — it hides a dispatchable card behind a blocker that does not exist. That is precisely the reasoning I gave you for #779; scoping it to the non-reproducer branch for #698 was an oversight in my drafting.pm:blockedon #779 because it lacked authorisation to write the label (authorised only alongside a close), not because it judged the label true. Absence of authority, not a verdict.Q2 — #520 closed without a browser rendering the dashboard. Acceptable? Yes, the close stands — and the reasoning that makes it acceptable is specifically that you did not assume the console's behaviour: you read the preset→macro mapping out of the shipped bundle and drove 21/21 combinations through the exact spelling the console emits, against SQLite ground truth, then replayed 7 service-dashboard widgets windowed with 0 blank and 0 disagreeing.
The decisive point is one you made and I am ratifying: the dateRange picker is not in the product right now — restoring it is what #1157 is for. A browser pass today would have nothing to exercise. Blocking a close on a visual confirmation that is currently impossible would be theatre.
Recorded as the falsifiable residual: what remains unverified is console rendering, not the platform defect #520 was filed about. If #1157's browser-verify step finds the Service dashboard blank with a working picker, this close was wrong and #520 gets reopened on that reading. That condition is now written down rather than left as a soft spot.
Filing objectstack#8690 separately instead of folding it into #520 was the right instinct — same blank-screen symptom, different cause. The symptom keeps a live upstream card even though #520 closed, which is what keeps the close honest.
The pattern this round makes undeniable
#691 is the third half-fixed card in this sub-issue alone (#698, #1141, #691), on top of #706's inversion and #788's "intended behaviour" verdict. Its 403 → 422, so the literal symptom moved, while the inconsistency the card was actually filed about is untouched — a pass/fail retest reports that as "fixed".
Across the whole sweep, rc-era cards are turning out to have partial fates far more often than binary ones. Any future close-out that asks "still broken? y/n" will systematically over-close. That belongs in the sweep's conclusions on #1150.
Three original repros were structurally unable to fail and were rebuilt (#698 half a, #701, #520), and two probes caught their own defects mid-run and reported INCONCLUSIVE rather than green. That is the standard.
2 closed, 4 survivors mirrored, 1 follow-up (#1157), 0 code changes, 0 labels overstepped.
Generated by Claude Code