Skip to content

sweep(spec): 3-item "self-descriptions answerable to reality" sweep — one claim, one PR, per-item checklist (#6242 #4895 #4837) #7024

Closed

Description

@os-zhuang

Sweep card per the findings-round bundling discipline (#6243 / PR #6288 precedent), packaged by the domain:spec seat with the maintainer's approval (2026-08-09 「同意」, chat). This card is the claim object; the member cards keep pm:queue but are NOT dispatch candidates while this sweep is open — selection excludes them via this member list.

Shared criterion (what makes these one sweep)

Every member is a self-description that stopped being answerable to reality — an enumeration, ledger verdict, or tombstone prose that asserts something the code no longer (or never) backed. Every fix re-anchors the description to a verifiable source of truth. No acceptance-face changes anywhere in this sweep — the legal-metadata set must be byte-identical before/after (that is the sweep's red line; a member that turns out to need an acceptance change is DROPPED from the sweep and reported, not smuggled).

Members (read each card in full before touching it; premise-first per member)

  1. Six independent enumerations of the stack-collection set, none answerable to stack.zod.ts — one is mis-aimed and two still list retired kinds #6242 — Six independent enumerations of the stack-collection set, none answerable to stack.zod.ts; one is mis-aimed and two still list retired kinds. Fix: make each enumeration derive from (or be pinned against) the schema's own set.
  2. audit: #4667 liveness 判定的跨仓覆盖核查——两个方向各有一个实锤反例;顺带更正 homePageId 墓碑文案 #4895 — The 清空剩余 6 条 authorWarn 死键 —— book ×2 / job.id / translation.validationMessages / app.homePageId / app.areas[].order(ADR-0049,v17 限时) #4667 liveness-verdict cross-repo coverage audit: two directions each with one measured counter-example; plus the homePageId tombstone prose correction the card carries. Fix half = corrections + re-dated verdicts with evidence; findings beyond the card's own scope are filed separately (PD chore: version packages #10), not fixed here.
  3. liveness 台账把「消费端存在读取代码」当作 live 的证据,会漏掉「没有任何生产者传值」的死键(Seed.env 即如此) #4837 — The liveness ledger counts "a consumer read site exists" as live evidence, which misses producer-less dead keys (Seed.env was the specimen). Fix: the methodology note/criterion so a live verdict requires evidence on the producer side too, and re-verify the verdicts the old criterion demonstrably over-graded (re-grade with evidence; do not mass-flip).

Sweep rules (binding on the PR)

  • One PR, body carries a per-item checklist: one row per member — 落点 | before | after — reviewed row by row.
  • Fixes #6242 / Fixes #4895 / Fixes #4837 only for members actually completed; a dropped member gets a Part of note and the reason.
  • Zero changes outside the N items, self-certified: git diff --stat file list must map 1:1 onto the checklist.
  • Out-of-scope discoveries are filed as separate unassigned issues (PD chore: version packages #10), never folded in.
  • A member whose premise died (main moves ~18 merges/day) is dropped with evidence — that is a good outcome, not a failure.

Refs: #6243 (sweep pilot), #4667 (liveness base), objectstack#4949 (filing discipline).

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 9, 2026
  2. self-assigned this
    on Aug 9, 2026
  3. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    ContributorAuthor

    Claim: PM loop round 2 (maintainer-approved cloud bundling, 2026-08-09 「同意」)
    Session: session_01PiRUoQkTSBBmpyXBY3cVn2 (dispatching); implementation runs as an independent cloud session (own container)
    Branch: claude/issue-7024-ledger-truth-sweep
    Worktree: cloud session workspace (solo container)
    Domain: domain:spec
    File surface: the three members' faces — stack-collection enumeration sites (answerable to stack.zod.ts), packages/spec/liveness/* verdicts + methodology prose, homePageId tombstone prose; possibly scripts/ where an enumeration lives in tooling. ⛔ Zero acceptance-face changes (sweep red line). (Stop on breach; explain in the report.)
    Serial constraints cleared: members #6242/#4895/#4837 leave the dispatch pool while this sweep is open. In-flight siblings (#7015/#6815/#6617/#4914/#5488/#7018) are source-disjoint; generated-tree overlap possible via liveness/docs ⇒ rides the landing relay, ordered at collection.
    Container assessment: M bundle, mode:cloud single container (maintainer-approved; shared container currently carries 6 devs).


    Generated by Claude Code

  4. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    ContributorAuthor

    OS-DEV-REPORT

    {
      "issue": 7024,
      "status": "done",
      "branch": "claude/issue-7024-ledger-truth-sweep",
      "pr": 7032,
      "premise_still_valid": {
        "6242": "YES — re-verified against origin/main before touching it. Every row of the card still describes main (line numbers had drifted; the drift had not): `ragPipelines` still mapped in PLURAL_TO_SINGULAR / metadataArrayKeys x2 / ARTIFACT_FIELD_TO_TYPE with no schema declaration; `workflows`/`approvals`/`roles`/`profiles`/`policies` still iterated by both ObjectQL loops; `triggers`+`workflows` still in MetadataCategoryEnum; `data: 'dataset'` still present in ARTIFACT_FIELD_TO_TYPE; STACK_COLLECTION_COVERAGE still tracked 3 collections and was ratcheted against nothing.",
        "4895": "PARTIALLY — task 2 (homePageId tombstone prose) was already landed in #4709 and is NOT re-done here, exactly as the sweep card scopes it. Tasks 1 and 3 were still open and are what landed.",
        "4837": "YES — seed.json's `env` row still cited only the consumer read site (seed-loader.ts:91), and nothing in the gate or the README required producer-side evidence. The methodology defect was untouched."
      },
      "summary": "All three members completed; none dropped. (1) #6242 — new `pnpm check:stack-collection-maps` gate (root scripts/, wired into the lint job) derives the stack-collection set from ObjectStackDefinitionSchema (32 collections, via a mechanical `z.array(<X>Schema)` rule rather than a second hand-kept list) and reconciles all EIGHT enumerations against it in both directions; a deviation is legal only as a waiver row carrying its reason, and a stale waiver fails like a stale ledger row. 19 waiver rows, each written from the gate's own output. One code change: ARTIFACT_FIELD_TO_TYPE no longer aims the seed collection (`data:`) at the analytics kind name (`'dataset'`) — provably inert (SeedSchema has no `name`; the ingest loop skips nameless items), so no runtime change. (2) #4837 — `producer` field on ledger entries, resolved through the SAME resolver as `evidence` (a repo-local path that does not exist fails CI), plus the criterion in liveness/README.md and a `--producer-gap` worklist; six entries re-verified by hand and cited on both sides. (3) #4895 — `evidenceScope` (`in-repo` | `cross-repo`) with the README recording the four blind-spot cases and the symbol-graph method case 4 forces; the #4667 retirement batch re-verified cross-repo against objectui @c2fd1223.",
      "member_results": {
        "6242": "DONE — gate + waiver ratchet + the one inert-map correction. Writing the gate found two things the hand-audit had not: a SEVENTH enumeration (`APP_CATEGORY_KEYS`, packages/runtime/src/app-plugin.ts, carrying three retired kinds), and a divergence BETWEEN ObjectQL's two copies that neither list shows alone — `jobs`, `emailTemplates`, `tools`, `skills` register from a manifest and NOT from a nested plugin, so a package shipping them from a nested plugin registers nothing and stamps no ADR-0010 provenance (`capabilities` was added to that copy for this exact reason in #5870; nobody then asked what else the lists disagreed about). Recorded as a waiver with the measurement rather than fixed: closing it changes what a nested plugin registers at boot.",
        "4837": "DONE — criterion + field + gate validation + `--producer-gap` worklist + re-grade slice. `seed.env` restamped with both sides cited (since #4704 `load()` resolves the comparison environment itself at the one funnel every seeding path goes through). Audited the same-shape class in the seed / job / hook ledgers: `job.timeout`, `hook.retryPolicy`/`timeout`/`onError` all HOLD (the scheduler threads `{retryPolicy, timeout}` into svc.schedule at app-plugin.ts:875-876; the hook binder hands the authored hook to wrapDeclarativeHook at hook-binder.ts:221). No status flipped, and no mass re-grade — the card asked for evidence, not a sweep.",
        "4895": "DONE — task 3 is the `evidenceScope` field; task 1 is the cross-repo re-verification of the #4667 batch against objectui @c2fd1223, all six keys CONFIRMED with no counter-example: `app.homePageId` (objectui now REJECTS it in OuiAppSchema with a pin test; AppPreview ignores it with a pin test; RootLandingRedirect routes on isDefault), `app.areas[].order` (no renderer sorts areas — AppSchemaRenderer / AppSidebar / UnifiedSidebar iterate array order and only filter), `book.translations` + `book.groups[].translations` (objectui's own Book/BookGroup interfaces declare no `translations`), `job.id` (JobSchema loaded only for client-side metadata-admin validation), `translation.validationMessages` (objectui TRANSPORTS the key into the client i18n tree and TranslationPreview echoes it, but nothing resolves it — and translation.zod.ts:320 already says exactly that, so no correction was owed). The two surviving tombstone rows carry `evidenceScope: cross-repo` and the pinned commit."
      },
      "acceptance_face": "UNCHANGED — packages/spec/authorable-surface.base.json is byte-identical; no schema key added, removed or retired; `check:authorable-surface` green and the spec build did not rewrite the baseline. Three of the drift rows #6242 reports sit ON acceptance faces (MetadataCategoryEnum decides what a published artifact may declare); they are recorded as waivers with their reason rather than fixed, per the sweep's red line.",
      "scope_self_certification": "`git diff --stat origin/main...HEAD` = 15 files, each mapping onto exactly one checklist row: check-stack-collection-maps.mjs + package.json + lint.yml + packages/metadata/src/plugin.ts + its changeset (member 1); producer.mts + producer.test.ts + check-liveness.mts + liveness/README.md + its changeset (members 2+3); liveness/{seed,job,hook}.json (member 2); liveness/{app,book}.json (member 3). Nothing else. No generated products changed (content/docs/references untouched — no gen step was triggered).",
      "tests": {
        "build_first": "pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*' — 70/70 successful, run BEFORE any typecheck (#6371). Re-run after merging origin/main: the merge brought #7021, which moves a @objectstack/types export, and a stale dist made packages/rest fail typecheck until the rebuild — not this diff.",
        "consumer_sweep_direction": "PREFIX — `pnpm --filter '...@objectstack/spec' typecheck` (everything that DEPENDS on spec: metadata, objectql, runtime, rest, qa/dogfood, all examples). Green (#6218).",
        "unit": "pnpm --filter @objectstack/spec exec vitest run scripts/liveness/ — 8 files, 143 tests, green (8 new in producer.test.ts, each driving a failing direction).",
        "self_test": "node scripts/check-stack-collection-maps.mjs --self-test — 11 assertions over synthetic sources, driving BOTH failure directions (unwaived deviation; stale waiver) plus the parser's own regression (a paren inside prose must not truncate the schema).",
        "gates": "Every check:* gate ENUMERATED from .github/workflows/lint.yml, run one by one, not from memory — 46 root gates + 6 filtered (check:generated --reconcile-only, check:skill-docs, check:spec-changes, check:upgrade-guide, check:authorable-surface, check:doc-formula-expressions). All green. Plus `node scripts/check-adr-0087-registration.mjs --base origin/main` — green (2 non-breaking changesets, no declared-breaking change).",
        "lint_typecheck": "ESLint over every changed file clean; `pnpm --filter @objectstack/spec exec tsc --noEmit` clean.",
        "ci": "PR #7032, head 2606f275 — 27/27 checks completed, ALL success (ESLint: success; TypeScript Type Check: success; Spec property liveness: success; Test Core 1-3/3, Dogfood Regression 1-3/3, Dogfood Verify CLI, Temporal Conformance, Build Core, Check Changeset, Check PR Size, Validate Package Dependencies, ADR maintainer approval: success; Build Docs / Console Pin Gate: skipped)."
      },
      "open_questions": [
        "Decided per the card's rules rather than asked: #6242's open sub-decision on `data:` (map to seed / remove / waive) was resolved as REMOVE. Repointing at 'seed' would be new behaviour — seeds are applied by SeedLoaderService off the bundle and never registered as metadata items — and the entry was already inert, so removal is the only option with no runtime consequence. Recorded in the waiver row and in a comment at the site.",
        "Decided: #6242's triage asked for a cross-domain split (the engine-core enumerations as a sub-issue with Blocked-by). The sweep card supersedes it for this PR by scoping the fix as 'derive from or PIN against the schema's own set' — the pin covers all eight sites without editing any engine-core semantics, and every engine-core drift row is recorded as a waiver naming #6242. If the PM still wants the drift REMOVED, that is a follow-up in the engine-core lane and the ratchet will fail the moment it lands, which is the intended handshake.",
        "Not asked, but worth the PM's eye: the ObjectQL manifest-vs-nested-plugin divergence (jobs / emailTemplates / tools / skills) is a live gap for packages that ship those collections from a nested plugin, not just cosmetic drift. It is recorded as a waiver here because closing it changes boot behaviour and needs its own verification. It is the strongest candidate for the follow-up issue, and I did NOT file it separately because it is squarely inside #6242 row 3 — filing it would split a card this PR closes."
      ],
      "out_of_scope_findings": [
        "NONE FILED. Two candidates were considered and both were judged in-scope rather than out: (a) the seventh enumeration APP_CATEGORY_KEYS — same class as #6242's six, so it joined the gate instead of becoming a new card; (b) the ObjectQL two-copy divergence — inside #6242 row 3, recorded as a waiver with its measurement. One genuine near-miss was checked and dropped: objectui still carries a `validationMessages` passthrough and preview panel for a key spec retired in 17.0.0, but this repo's own translation.zod.ts:320 already documents that transport-without-consumption, so there was nothing new to file and the objectui-side residue is that repo's call.",
        "Coverage limit, stated rather than papered over: `cross-repo` in this sweep means objectui ONLY. The `cloud` runtime is not reachable from an open-source checkout, so no verdict here claims coverage of it — the README says so where the value is defined, so `cross-repo` cannot be read as 'everywhere'."
      ]
    }

    Generated by Claude Code

  5. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    ContributorAuthor

    ACCEPT → PR #7032 (all three members: Fixes #6242, #4895, #4837). Verified against GitHub: 15-file diffstat maps 1:1 onto the checklist; acceptance face byte-identical (authorable-surface untouched, check:authorable-surface green); CI 27 checks — 25 success + 2 path-filtered skips, ESLint and TypeScript Type Check both success.

    Review highlights: the gate DERIVES the collection set from ObjectStackDefinitionSchema instead of minting a ninth hand-kept list — the right anchoring; writing it found a seventh enumeration and a real ObjectQL two-copy divergence the hand audit missed; waiver-with-reason for acceptance-face drift rows honours the sweep's red line exactly. The engine-core drift rows staying as waivers is accepted — the ratchet failing the moment engine-core removes the drift is the intended cross-lane handshake. producer evidence resolving through the same resolver as evidence makes the new criterion machine-checked rather than prose.

    One follow-through executed by this seat (PD #10): the ObjectQL manifest-vs-nested-plugin divergence (jobs / emailTemplates / tools / skills register nothing when shipped from a nested plugin) is a live boot-behaviour gap that would lose its tracking entry when #6242 closes — filed as a separate finding (cross-referenced from this thread by the new issue) with the report's measurement quoted, for the triage seat to grade. The waiver row remains its machine anchor.

    Landing: pairwise disjoint with the other two cloud PRs — entering the queue first of the three.


    Generated by Claude Code

  6. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    ContributorAuthor

    Sweep complete — closing the claim card. PR #7032 merged to main at 3de535b86 (2026-08-09T12:04Z). All three members delivered and verified closed by direct reading: #6242 ✓, #4895 ✓, #4837 ✓ (each state_reason: completed, closed 12:04Z). No members dropped; the per-item checklist and 1:1 diff-stat self-certification are in the PR body. Acceptance-face red line held: no accept/reject changes anywhere in the sweep.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions