Skip to content

finding(types,i18n): eight doc comments claim alignment with @objectstack/spec symbols the spec does not export #4597

Description

@yinlianghui

Observation-class finding, measured while implementing #4592 (the spec-alignment claim rule). Nothing is changed for it there — #4592 owns scripts/** only, and these declarations belong to other surfaces. Filed so the next one is a decision rather than an accident.

What was found

Eight exported declarations carry a doc comment claiming alignment with a @objectstack/spec symbol that the installed spec (17.0.0-rc.6) does not export at all:

declaration file claimed spec symbol
SpecPluralRule packages/i18n/src/utils/spec-formatters.ts:28 PluralRuleSchema
SpecDateFormat packages/i18n/src/utils/spec-formatters.ts:90 DateFormatSchema
SpecNumberFormat packages/i18n/src/utils/spec-formatters.ts:133 NumberFormatSchema
SpecLocaleConfig packages/i18n/src/utils/spec-formatters.ts:179 LocaleConfigSchema
FieldChangeEntry packages/types/src/views.ts:398 FieldChangeEntrySchema
Mention packages/types/src/views.ts:417 MentionSchema
Reaction packages/types/src/views.ts:434 ReactionSchema
RecordSubscription packages/types/src/views.ts:449 RecordSubscriptionSchema

Verified by resolving @objectstack/spec from node_modules and enumerating every export name across every subpath (4834 names) — the same machinery scripts/check-spec-symbol-derivation.mjs already uses. None of the eight names appears.

Example, packages/types/src/views.ts:434:

/**
 * Reaction — An emoji reaction on a feed item.
 * Aligned with @objectstack/spec ReactionSchema.
 */
export interface Reaction { ... }

Why it may matter

This is the harm the derivation guard's own header argues, in its purest form: "a wrong canonical-claim is not stale documentation — it is a planted premise for the next session." A drifted claim at least points at something real, so a reader can compare and find the difference. A dangling claim points at nothing: the next agent goes looking for the spec's ReactionSchema to check the shape against, does not find it, and has no way to tell whether the spec retired it, renamed it, never had it, or the comment was always wrong.

It is also the sub-class that no structural instrument can reach. #4592 measured the alternative — comparing local key sets against spec object types — and it cannot see any of these eight, because there is no spec-side shape to compare against. Only the prose says anything at all.

Note that whether each declaration's SHAPE is right is a separate question this finding does not answer; several may be perfectly good local types that simply mis-cite their provenance.

Deliberately not established here

  • Whether the spec ever exported these names. Not researched. They may be pre-17 names retired long ago (#3362 is that pattern), names from a different package, or names that never existed. The fix differs per case: re-point the comment, derive from whatever the spec calls it now, or delete the claim.
  • Whether any of the eight shapes has drifted from whatever the spec models today under another name.
  • Priority. No user hits this and no metadata is refused; it is a provenance-accuracy observation about comments, which is why it is filed as an observation rather than a defect.

All eight are named individually in the shrink-only CLAIM_DEBT ledger added by #4592, so the gate reports them and none can silently acquire a fresh unbacked claim. Burning one down is a one-line ledger edit plus the comment fix.

Refs #4592, #4588, #3103, #3561.


Generated by Claude Code

Activity

  1. self-assigned this
    on Aug 13, 2026
  2. yinlianghui commented on Aug 13, 2026

    @yinlianghui
    CollaboratorAuthor

    CLAIM — session session_017Qqyix2QcnpUC9XeYVDzx3, branch claude/issue-4597-dangling-spec-citations. Code work starts only after PR #4604 lands (shared CLAIM_DEBT ledger block; it is armed now).

    PM ruling (delegated, veto window open) — measure per symbol, then the honest fix for that symbol:

    1. Measure each of the 8 cited symbols (DateFormatSchema, NumberFormatSchema, PluralRuleSchema, LocaleConfigSchema in i18n's spec-formatters; FieldChangeEntrySchema, MentionSchema, ReactionSchema, RecordSubscriptionSchema in types/views.ts) against: (a) the INSTALLED @objectstack/spec@17.0.0-rc.6's full export surface across ALL subpaths (the hardened gate's own enumeration machinery is the arbiter); (b) whether a symbol of that meaning exists under a DIFFERENT name in rc.6; (c) the spec's latest published version if reachable through the proxy — if unreachable, say so and grade on (a)+(b) alone.
    2. Fix hierarchy per symbol: exists under another rc.6 name ⇒ bind/derive to the real name or correct the citation; exists only in a NEWER spec ⇒ the claim is premature — either reword to name the true state ("anticipates X, not yet in the pinned spec") or leave that comment untouched for the pin bump (its ledger entry then STAYS — partial burn-down is legal, the ratchet only rejects stale entries); exists nowhere under any name ⇒ delete or reword the claim sentence so the comment stops vouching for a phantom.
    3. Ledger: delete the CLAIM_DEBT entries for exactly the symbols whose claims you fix — ratchet Implement component reordering via drag-and-drop in designer canvas #5 is your red-first (fix applied + entry present ⇒ gate REDS verbatim; entry deleted ⇒ green with counts dropping). Surgical lines only, nothing else in scripts/**.
    4. Grading: doc-comment changes on exported declarations LAND in the published .d.ts — measure both ways; comment-only deltas ⇒ patch per package if the presence gate demands entries (the fix(mobile): SpecResponsiveConfig derives from its claim's source (#4598) #4604 plugin-grid precedent), never major.

    Mutual exclusion: ⛔ packages/types/src/base.ts + packages/react + packages/layout + app-shell = #4581-remainder's in-flight seat (your types surface is views.ts only); ⛔ content/docs/releases/**. This is a comments-and-ledger card — zero runtime or type-shape change; any tempted shape edit is a STOP.


    Generated by Claude Code


    Generated by Claude Code

  3. yinlianghui commented on Aug 13, 2026

    @yinlianghui
    CollaboratorAuthor

    PM step-7 复核: ACCEPT. PR #4606 is the measurement standard this card needed: all three ruling branches tested per symbol, and the finding that reshaped the fix — all eight were REAL exports the protocol deliberately retired (the feed four at 16.0.0, the i18n four at rc.6 itself under ADR-0049), with rc.6's own CHANGELOG and shipped retirement notes as corroboration rather than inference, and every local key set faithful to the schema it named. "Record the expired citation with provenance" is the right fix for that truth, and rejecting CLAIM_ALLOW because it would preserve a false sentence (ratchet #6 would demand the claim stay) is exactly the correct reading of the instrument. The FieldChangeSchema wrong-re-point warning written INTO the comment is the highest-value line in the diff — it defuses the one near-miss a future agent would plausibly bind to. Honest reverse-verification direction note (green→intermediate-RED→green is a ledger card's correct shape), comment-strip .d.ts proof via the TS printer, patch grading with the empty-frontmatter exemption explicitly rejected for the right reason.

    The same-file collateral is ACCEPTED, including item (c): the FeedItem/FeedItemSchema citation is this card's exact defect class inside this card's declared file — leaving it while fixing its four siblings would have been self-contradictory. The ledger comment's new "retired vs never-existed" guidance for the next measurer is a welcome addition.

    #4607 (rule 2's symbol-agnostic tie test — the FeedItem specimen) is a real precision gap and enters the pool as the natural continuation of #4592's instrument.

    Flipping ready and arming auto-merge now.


    Generated by Claude Code


    Generated by Claude Code

  4. added a commit that references this issue on Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions