Skip to content

lint: liveness-dead-property and liveness-live-elsewhere-property cannot fire on 17.3.0 — 90 dead + 1 live-elsewhere ledger rows and not one sets authorWarn #16094

Description

@os-steve

Measured on the pinned @objectstack/lint@17.3.0 + @objectstack/spec@17.3.0 artifacts as installed by objectstack-ai/hotcrm, ⛔ not on the platform source tree. Filed unassigned by the hotcrm step-3 rule survey (hotcrm#1613); the local assertion currently standing in for these stays in place there.

The gap

lintLivenessProperties only considers a ledger row when shouldWarn accepts it:

function shouldWarn(entry) {
  if (!entry) return false;
  return entry.authorWarn === true || entry.status === "experimental";
}

describe(entry) then maps status: 'dead' to LIVENESS_DEAD_PROPERTY and status: 'live-elsewhere' to LIVENESS_LIVE_ELSEWHERE_PROPERTY. Both branches are unreachable on this pin, because no row with either status opts in.

Enumerating every props entry (children included) across all 36 files in @objectstack/spec/liveness/:

status histogram: live 636 · dead 90 · planned 14 · experimental 5 · live-elsewhere 1 · (unset) 34

every row shouldWarn accepts:
  action.json       operation             planned      authorWarn: true
  action.json       patch                 planned      authorWarn: true
  field.json        relatedListFilter     planned      authorWarn: true
  object.json       externalSharingModel  planned      authorWarn: true
  translation.json  flows                 planned      authorWarn: true
  agent.json        lifecycle             experimental
  agent.json        memory                experimental
  agent.json        guardrails            experimental
  agent.json        structuredOutput      experimental
  tool.json         outputSchema          experimental

Ten rows, all planned or experimental. Zero dead, zero live-elsewhere. So the only rule ids the liveness linter can emit today are liveness-planned-property and liveness-experimental-property; the other two are dead code paths against this ledger, and authorWarnedProperties(type) returns a non-empty set for exactly three types (object, field, action).

Measurement, with a working control

One committed tree (hotcrm at a0362a37), one injection at a time, restored by blob hash. Clean-tree baseline: 0 error(s), 17 warning(s), 12 suggestion(s), exit 0.

injection result
controlexternalSharingModel: 'private' on crm_account (a row that DOES set authorWarn) liveness-planned-property warning, exit 0
a schema-legal list.tabs: [{ name, label }, …] on crm_account's list view no liveness-* finding — 17 warnings, exit 0, byte-identical to baseline

The control fires in the same harness on the same command, so the second row is a reading about the ledger, not about the linter being off.

The second half, and it points the other way

hotcrm carries test/view-tab-label-inert.test.ts, which asserts that no list / listViews block declares tabs at all. Its premise (hotcrm#1307) is that the object-view switcher never reads list.tabs, so authoring one is inert metadata. The pinned ledger disagrees:

view.json   list.tabs   status: live

So even if the dead rows were opted in, this particular key would be judged live and the rule still would not fire on it. One of the two readings is wrong and it would be good to know which — that is a question for whoever owns view.json, not something this survey can settle. (Note list.tabs is schema-accepted with member shape { name, label }; a { key, label } member is refused outright by ViewTabSchema, which is a different mechanism.)

Suggested direction, not a prescription

Two separable asks:

  1. Decide whether the dead and live-elsewhere verdicts should imply authorWarn rather than requiring a per-row opt-in. Ninety rows carrying a verdict the author lint can never surface is a large silent surface, and ADR-0049's enforce-or-remove loop is exactly the consumer that wants it.
  2. Re-derive view.json's list.tabs verdict against the shipped switcher.

⚠️ Both LIVENESS_DEAD_PROPERTY and LIVENESS_LIVE_ELSEWHERE_PROPERTY are currently untestable end to end for the same reason, so whichever way (1) goes, a pin proving each id can be produced would keep this from regressing quietly.

Related, and why this is not a duplicate

Refs: hotcrm#1613 · hotcrm#1582 (the family card) · hotcrm#1307 (the list.tabs premise)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions