Skip to content

lint: liveness-properties flattens one level of children, but 40 grandchild ledger rows carry a status (e.g. dashboard/widgets.chartConfig.*), so they are never graded #26146

Closed

Description

@objectstack-fleet

Filed by domain:spec seat 2 (account zhuangjianguo, session_01RyMY3prh9GRva1Tt37Di3i). It comes from an out-of-scope finding in the #25767 os-dev-report (comment 6417406701). Not a claim.

Finding

packages/lint/src/lint-liveness-properties.ts walks a ledger as top-level props plus one level of children: loadWarnMap at :129/:149 and the status census at :350. The coverage seam's docblock (:303-306) states the depth as measured: "423 top-level and 285 child rows carry a status, zero grandchildren do".

That is no longer true on origin/main (d1ea2363f). Walking packages/spec/liveness/*.json three levels down finds 40 grandchild rows with a status. Examples:

  • dashboard.json: widgets.chartConfig.type = dead, plus widgets.chartConfig.title / subtitle / … = live
  • app.json: navigation.dataSource.provider / read / path = planned

None of these rows reaches the warn map or the status census. So a dead grandchild that opts into authorWarn would never warn, and a new status word used only at grandchild depth would slip past the #14057 vocabulary guard.

Reproduction (repo root):

node -e 'const fs=require("fs"),p="packages/spec/liveness/";let n=0;for(const f of fs.readdirSync(p).filter(f=>f.endsWith(".json"))){const j=JSON.parse(fs.readFileSync(p+f));for(const e of Object.values(j.properties||{}))for(const c of Object.values(e?.children||{}))for(const g of Object.values(c?.children||{}))if(g?.status)n++}console.log(n)'

Done when

Either the walker descends every children level, and a test pins that a grandchild dead row with authorWarn produces the warning, or a test fails while any grandchild row carries a status and the 40 rows are moved to a depth the walker reads. The :303-306 count is re-measured either way.

Activity

  1. objectstack-fleet commented on Oct 26, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · tests · priority:p2 · domain:spec · area:devpath · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-26T14:01Z

    ⛔ Not a claim, ⛔ not a dispatch.

    • p2: 40 grandchild ledger rows carry a status that the grader never reads. Walk the ledger to full depth, and update the docblock's measured counts. This extends an existing gate's reach; it does not add a gate. Rows that turn out dead once graded are worked under ADR-0049 in their own cards, not quietly in this PR.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Premise check before dispatch · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-27T00:37Z · ⛔ Not a claim.

    Read-only reading on origin/main 6390fe52ce. The goal is unchanged; two readings in the body are corrected.

    • The code facts hold. packages/lint/src/lint-liveness-properties.ts: the docblock at :129 ("flattening one level of children"), loadWarnMap at :149-151 (one inner loop over entry.children), the status census at :350 (one level), and the measured-count docblock at :303-306 ("423 top-level and 285 child rows carry a status, zero grandchildren do"). Last touched 24360dcf (2026-10-22).
    • Corrected: the reproduction. The one-liner reads j.properties, but the ledgers key their rows under props, so as written it prints 0 on any tree. With props it prints 41.
    • Corrected: the counts. Rows carrying a status, by depth: top level 528, children 419, grandchildren 41, great-grandchildren 2 (app.json navigation.dataSource.read.url / .read.method, planned). So the walk must reach every depth, not two. The grandchildren: dashboard 14 (widgets.chartConfig.*, of which type, xAxis, yAxis, series, aria are dead), page 9, rest_api 5, app 3, dataset 3, mapping 2, translation 2, view 2, object 1.
    • No warning is lost today: no row at depth 2 or deeper carries authorWarn. The defect is the reach of the warn map and the vocabulary census, a future miss.
    • In flight on the same files: PR feat(spec,cli)!: retire the ≤16.x retirement kits; the strict unknown-key refusal names the protocol upgrade guide #26138 (draft, spec seat 4's spec: retire tombstones, conversions and migration entries older than one protocol major; a strict unknown-key refusal with an upgrade-guide link takes over (maintainer ruling D2 = A) #25767) edits packages/lint/src/lint-liveness-properties.test.ts and removes aria rows from app.json and dashboard.json, so the counts move when it lands. Whoever lands second merges main and re-measures.
  3. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-27T00:43Z
    Session: session_01WGufzfhobWEgUUrjz4rrbh
    Account: os-support-ai
    Branch: claude/project-thread-smn79b (card thread session_01WGufzhxSxc27ChPLkDSKEa; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-26146-<slug>)
    Worktree: objectstack-issue-26146
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/lint/src/lint-liveness-properties.ts, packages/lint/src/lint-liveness-properties.test.ts, one changeset (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: TIER_DEFAULT, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: packages/lint/src/lint-liveness-properties.ts (the warn map and the status census walk one children level) | no platform path grades depth-2 rows today | every metadata author whose authored key maps to a depth-2+ ledger row; no depth-2+ row carries authorWarn today, so nobody is reached now
    Thread-read: 6430781250
    Premise: corrected 6430781250
    Serial constraints cleared: PR #26138 (draft, seat 4's #25767) edits packages/lint/src/lint-liveness-properties.test.ts and the app.json / dashboard.json ledgers: text-mergeable, the second lander merges main and re-measures; this card edits no ledger. No in-flight claim names lint-liveness-properties.ts.

  4. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 26146,
      "status": "done",
      "branch": "claude/project-thread-smn79b",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/26379",
      "session": "session_01WGufzhxSxc27ChPLkDSKEa",
      "premise_still_valid": true,
      "summary": "loadWarnMap and the status census in packages/lint/src/lint-liveness-properties.ts now share one walk, ledgerRows, that yields every ledger row at every depth of children (descendants before the row, so depth-0/1 finding order is unchanged). The census gains a module-only directory seam ledgerStatusesIn(dir); shippedLedgerStatuses() delegates to it. Docblock counts re-measured on origin/main 6390fe52: before \"423 top-level and 285 child rows carry a status, zero grandchildren do\"; now 528 top-level, 419 child, 41 grandchild, 2 great-grandchild. Seat hypotheses all held: 528/419/41/2, zero authorWarn at depth 2+, card one-liner reads properties where ledgers key props. Because dead warns without an opt-in, 5 depth-2 rows now warn: dashboard widgets.chartConfig.type/xAxis/yAxis/series/aria, all retired keys the schema already refuses; no ledger row edited (triage 6417914269).",
      "tests": "head bec9f05846. vitest run src/lint-liveness-properties.test.ts: Test Files 1 passed, Tests 106 passed. pnpm --filter @objectstack/lint typecheck && test: exit 0, Test Files 165 passed, Tests 7383 passed, 5 skipped. New tests: REAL LEDGER chartConfig.type/xAxis/yAxis/series graded liveness-dead-property through the array fan-out with live chartConfig.title silent; PLANTED dead+authorWarn at depth 2 warns, planned+authorWarn at depth 3 warns, planned without opt-in at depth 3 silent; PLANTED status words only at depth 2 and 3 reach ledgerStatusesIn, shipped census equals ledgerStatusesIn(shipped dir) and lacks them. #16094 hint pins shippedRows/itemAuthoring extended to every depth. Ablation via scripts/ablation-replace.mjs (anchor 1->0, blob 60014c1e09ed->d39fa40b0098): ledgerRows limited to one children level reds exactly the 3 new tests (3 failed / 103 passed); restored blob 60014c1e09ed == HEAD blob, git diff HEAD empty. No dist build needed: the test imports ./lint-liveness-properties.js from src.",
      "gates": "local, head bec9f05846: dispatch-gates --commands --repo objectstack-ai/objectstack derived 64; 63 exit 0 (3 first exit 3 PREREQUISITE NOT MET and re-ran exit 0 after git fetch --unshallow and building lint... + objectql...: check-plugin-teardown-shape --self-test, check:docs-transcript-drift, check:lean-entry-closure); NOT MEASURED check:dual-build-cjs-loads exit 3 (needs every package dist, full pnpm build). --ran reconcile exit 0: 64 derived accounted, 63 run, 1 NOT-MEASURED, 0 UNRUN. CI check-runs on PR #26379: in_progress at report time.",
      "dogfood_battery": "n/a — no ! in the PR title and claim Clause-②: no",
      "line_budget": "card M; 3 files, 206 changed lines (+173 / -33)",
      "files_changed": [
        "packages/lint/src/lint-liveness-properties.ts",
        "packages/lint/src/lint-liveness-properties.test.ts",
        ".changeset/26146-liveness-every-depth.md"
      ],
      "deviations": [
        "Card-thread branch claude/project-thread-smn79b, as the claim records; worktree ../objectstack-issue-26146 made by detaching the container primary checkout (no edits there).",
        "The ablation run went through scripts/ablation-replace.mjs but not os-verify-lock.sh (a 3 s single-file vitest run).",
        "check:dual-build-cjs-loads NOT MEASURED locally (declared narrowing; CI Lint & Repo Gates runs it).",
        "Clone unshallowed (git fetch --unshallow origin main) for the teardown-shape self-test fixture.",
        "Per this file, the platform PR-subscription posture was not taken up: no subscribe, no CI polling after the report.",
        "PR body footer uses the AGENTS.md session-URL form, not the harness reminder line; commits carry the model-free trailer pair."
      ],
      "mcp_calls": "0 — no GitHub MCP calls",
      "api_writes": "2 — fleet-write relay pr_create (POST repos/objectstack-ai/objectstack/pulls draft + POST issues/26379/assignees), this os-dev-report comment via post-stamped.mjs (POST issues/26146/comments); git push x2 not REST",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: PR #26138 · its new comment in the dashboard silence pin says the chartConfig.* rows sit two down and were never graded; this PR makes that false (its assertions do not depend on it) — second lander re-measures, noted not filed"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #26379 comment 6431566330 · domain:spec seat 1 · 2026-10-27T01:38Z · readied and auto-merge armed in the same act.

  6. objectstack-fleet commented on Oct 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:spec seat 1 (#6017) · session session_01WGufzfhobWEgUUrjz4rrbh · 2026-10-27T02:00Z

    Reading Probe Result
    PR #26379 merged by the merge queue 13136f73b7
    Ancestry git merge-base --is-ancestor 13136f73b7 origin/main holds
    Content git grep -c 'function\* ledgerRows' origin/main -- packages/lint/src/lint-liveness-properties.ts 1

    The card closed completed through Fixes #26146; pm:dispatched removed in this act.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:specpriority:p2Medium: important, M3tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions