test(cli),fix(sharing): migrate-meta end-to-end proof + inert-rule warn dedup — the last two finishing touches - #4066
Merged
Conversation
…ver a pre-17 project The chain's transforms were fixture-tested in spec, but the COMMAND path — bundleRequire config loading, the convert:false normalization that keeps rewrites attributable to chain hops, the schema-validity verdict, the machine JSON shape, --out snapshots, the support-floor refusal — had no test. Spawns bin/run-dev.js against a temp project authored in the pre-17 dialect (one key from every v17 conversion family in a single pass) and pins: - all 11 v17 conversion families attribute at least one rewrite; - semantic TODOs surface with reason + acceptanceCriteria, never auto-apply; - the --out snapshot re-parses under the CURRENT schema, with per-family spot-checks (execute→target, storage.notNull stamped on the required field and NOT on the optional one, full→edit, every close-out key gone, and the canonical protocol-11 filter key passing through untouched); - CHAIN IDEMPOTENCE end-to-end: replaying --from 16 on the migrated snapshot applies zero changes and stays schema-valid; - --from 9 exits non-zero with the structured unsupported_from_major error. Fixture authoring found one doc-comment error in my own draft: the filters→filter alias is protocol-11 dialect, not 16 — a 16-authored source already says filter, and the test now pins the pass-through instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QuViRSR1j6GJjf9qGbnqFX
The fail-closed evaluator warned on EVERY pass (findMatchingRecords per evaluation AND recordMatches per reconciled write) — one legacy criteria-less rule could dominate a deployment's log. Now: once per rule per process (instance Set, message says so and names the fix), plus one aggregate line from the boot backfill (count + rule names). Enforcement unchanged on every pass — the dedup test pins zero grants throughout and that the backfill walk does not re-warn per rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QuViRSR1j6GJjf9qGbnqFX
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 21 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
os-zhuang
marked this pull request as ready for review
July 30, 2026 08:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent finishing touches on the #3896 line, batched as one small PR now that the close-out sweep (#4054) is merged.
1.
os migrate metagets its end-to-end proof (packages/cli/test/migrate-meta.e2e.test.ts)The chain's transforms are fixture-tested in
@objectstack/spec, but the COMMAND path — config loading via bundleRequire, chain attribution, the schema-validity verdict, the machine JSON shape,--outsnapshots, the support-floor refusal — had no test at all. This spawns the REAL CLI (bin/run-dev.jsvia tsx) against a temp project authored in the pre-protocol-17 dialect, exercising one key from every v17 conversion family in a single pass — exactly the cross-major "consumer upgrades" scenario the command exists for.Six tests pin:
schemaValid: trueon the migrated output, with all 11 expected v17 conversion ids attributed at least one rewrite each (renames, the ADR-0113required→storage.notNullexplicitization, and everyPOST /data/sharing/rules绕过SharingRuleSchema:criteria缺失或拼错静默变成"共享该对象全部记录",与 ADR-0049 "never seeded as a permissive match-all" 直接冲突 #3896 removal family);--outsnapshot re-parses under the CURRENTObjectStackDefinitionSchema, with one spot-check per family (target='closeHandler',accessLevel='edit',storage:{notNull:true}on the required field and nothing on the optional one, canonicalfilterpassing through untouched);unsupported_from_majorerror, not a stack trace.2. Inert-rule warn dedup + boot aggregate (#3929 follow-up)
isInertMatchAllwarned on EVERY pass —findMatchingRecordsper evaluation ANDrecordMatchesper reconciled write — so one bad rule spams production logs. Two layers now:sharing-rule-service.ts): ainertRuleSeenset keyed byrule.id ?? rule.namelogs once per rule per process, and the message says so ("fix the criteria or setactive: false"). A readonlyinertRuleNamesaccessor exposes the set.sharing-plugin.ts):backfillRuleGrantsemits ONE summary warn after the loop with{count, rules}— the rules matching no records, whose grants are revoked on reconcile (ADR-0049).Enforcement is unchanged — inert rules still match zero records; only the logging is deduplicated. The new boot-backfill tests pin exactly that: 2 inert rules × 4 evaluations → exactly 2 per-rule warns (per DISTINCT rule, not per pass), zero
sys_record_sharewrites throughout, exactly 1 aggregate withcount=2and sorted rule ids, no re-warn during backfill.Verification
tscand ESLint clean; patch changeset for@objectstack/plugin-sharing(the e2e test is test-only, no changeset needed).Generated by Claude Code