Repository navigation
sweep(spec): three self-descriptions re-anchored to a verifiable source of truth (#6242 #4895 #4837) - #7032
Merged
Conversation
…le source of truth (#7024) Sweep card #7024 — every member is a self-description that stopped being answerable to reality, and each fix re-anchors it to something checkable. #6242 — eight enumerations of the stack-collection set, none answerable to `stack.zod.ts`. New `pnpm check:stack-collection-maps` derives the set from `ObjectStackDefinitionSchema` and reconciles all eight against it in both directions; every deviation is a waiver row carrying its reason, and a stale waiver fails like a stale ledger row. Writing it found a seventh site the hand-audit missed (`APP_CATEGORY_KEYS`) and a divergence between ObjectQL's two copies that neither list shows alone. One code change: `ARTIFACT_FIELD_TO_TYPE` no longer aims the seed collection (`data:`) at the analytics kind (`'dataset'`) — a provably inert entry pointed at the wrong kind. #4837 — the ledger counted "a consumer read site exists" as `live` evidence, which misses producer-less dead keys (`Seed.env`). Adds the `producer` field (resolved like `evidence`, so a call-site claim cannot rot), the criterion in liveness/README.md, and a `--producer-gap` worklist. Six entries re-verified by hand; `seed.env` restamped with both sides cited. #4895 — adds `evidenceScope` (`in-repo` | `cross-repo`), and re-verifies the #4667 retirement batch cross-repo against objectui @c2fd1223: all six keys confirmed, no counter-example. The two surviving tombstone rows carry the scope and the pinned commit. ⛔ Zero acceptance-face changes: authorable-surface.base.json is untouched, and the three drift rows that sit on acceptance faces are recorded as waivers rather than fixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3ydyJV9reKBgoez8LAoqY
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 114 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This was referenced Aug 9, 2026
os-zhuang
marked this pull request as ready for review
August 9, 2026 11:44
This was referenced Aug 9, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Aug 17, 2026
…`tools` / `skills` — the two registration copies become one enumeration (objectstack-ai#7049) (objectstack-ai#7153) * fix(objectql): register jobs / emailTemplates / tools / skills from a nested plugin too (objectstack-ai#7049) `engine.ts` reaches the ADR-0010 provenance-stamping seam (`registerItem` -> `applyProtection`) from two entry points -- a manifest and a nested plugin -- and each carried its OWN copy of the collection list. The copies had drifted by four collections: `jobs`, `emailTemplates`, `tools` and `skills` registered from a manifest and NOT from a nested plugin, so a package shipping any of them via `manifest.plugins[]` registered nothing and stamped no provenance -- no refusal, no diagnostic. Hand-adding the four names was the available alternative and is exactly what objectstack-ai#5870 did for `capabilities`; it is what left these four undiffed. Measured the two loops against each other instead: they differ in which object they read, which package id they stamp (both resolve to the same parent package), a per-key `debug` line, and the manifest seam's aggregated-view expansion plus its warn-on-nameless-item. All four are loop-BODY differences; none is a reason for the seams to enumerate different collections. So the enumeration is hoisted to one module-scope `METADATA_ARRAY_KEYS` both seams read, and the divergence is unrepresentable rather than merely unnoticed. `check:stack-collection-maps` now pins one ObjectQL enumeration instead of two, and the waiver row recording the divergence is removed in the same change -- objectstack-ai#6242's ratchet handshake: 8 enumerations / 19 waiver rows -> 7 / 16. Tests pin each of the four registering AND carrying `_packageId` / `_provenance` from a nested plugin, plus the seams' agreement as a property over every comparable collection rather than over the four that happened to diverge. Refs: objectstack-ai#7049, objectstack-ai#7032, objectstack-ai#6242, objectstack-ai#5870, objectstack-ai#4509, ADR-0010. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXFj4BYpeUHyTX4eqirbeQ * docs(objectql): name the filed card for the views-expansion seam difference (objectstack-ai#7163) The `views` exclusion in the seam-agreement sweep is out of scope for objectstack-ai#7049 by measurement, not by convenience: one aggregated container registers ['account', 'account.all_accounts', 'account.form'] from a manifest and ['account'] from a nested plugin. Filed as objectstack-ai#7163; recording the issue number and the measured values so the exclusion is falsifiable from the test file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CXFj4BYpeUHyTX4eqirbeQ --------- Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Sep 1, 2026
…, floor its vacuous pass, and correct what the sibling gate claims about its own failure mode (objectstack-ai#13050) * fix(scripts): reconcile the dual-build ledger in the orphan direction, and floor its vacuous pass An exemption row whose id left the population was read by nothing: the only lookup was `ledger[r.id]` from inside the walk over discovered rows. Measured on 8cb96ec — a row exempting a package that does not exist left the pass line byte-identical, exit 0, the id unmentioned. Adds the ledger -> population pass, and four vacuity floors (entries, packages, emitted CommonJS files, behaviour probes) that REFUSE (exit 2) rather than report the clean tree when the sweep read nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw * docs(scripts): correct check-stack-collection-maps' account of how SECURITY_FIELDS went unread The header said the flat extractor 'could not read it and the site was skipped instead of failing'. Re-measured on 8cb96ec: false. This gate has refused an empty extraction since objectstack-ai#7032, and swapping the site's extractor back to stringArrayItems exits 1 by name. The site was skipped because it was never a SITE — SECURITY_FIELDS occurred 0 times in this file before objectstack-ai#13009 (control ARTIFACT_FIELD_TO_TYPE: 5). The hole was the hand-written SITES population, not the extractor set. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
Fixes #6242
Fixes #4895
Fixes #4837
Sweep card #7024. All three members completed; none dropped. Shared criterion: each member is a self-description that stopped being answerable to reality, and each fix re-anchors it to something checkable.
Per-item checklist
1. #6242 — eight enumerations of the stack-collection set, none answerable to
stack.zod.ts落点
scripts/check-stack-collection-maps.mjs(new),package.json,.github/workflows/lint.yml,packages/metadata/src/plugin.tsbefore
ObjectStackDefinitionSchemadeclares 32 collections. Seven other places re-enumerate that set by hand (eight enumerations — ObjectQL declares its list twice), and nothing compared any of them to the schema or to each other.ragPipelinesmapped in three sites though no schema declares it;workflows/approvals/roles/profiles/policiesstill iterated by both ObjectQL loops after four ADRs retired them;triggers+workflowsstill legal artifact categories; 19 of 32 collections absent from that enum;ARTIFACT_FIELD_TO_TYPEaimed the seed collection (data:) at the analytics kind name ('dataset').after
pnpm check:stack-collection-mapsderives the set from the schema (top-level keys whose value isz.array(<X>Schema)— mechanical, not a second hand-kept list) and reconciles all eight enumerations against it in both directions. Deviations are legal only as waiver rows carrying a reason, and the list is a ratchet: a waiver that no longer applies fails, like a stale ledger row. An enumeration whose symbol cannot be extracted fails too — an empty list would reconcile against everything. 19 waiver rows landed, each written from the gate's own output. One code change: thedata: 'dataset'entry is removed (provably inert —SeedSchemadeclares nonameand the ingest loop skips nameless items — so no runtime change; not repointed at'seed', which would be new behaviour).Two things the gate found that the hand-audit had not:
APP_CATEGORY_KEYS(packages/runtime/src/app-plugin.ts), carrying three retired kinds;jobs,emailTemplates,tools,skillsare registered 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.capabilitieswas added to that copy for exactly this reason (capabilities不在 ObjectQLmetadataArrayKeys注册缝里 —— app 声明的 capability 永远拿不到 registry provenance(#4967 Part 2 拆出) #5870); nobody then asked what else the two lists disagreed about. Recorded with the measurement, not fixed here.2. #4837 — the ledger counted "a consumer read site exists" as
liveevidence落点
packages/spec/scripts/liveness/producer.mts(+ test, new),check-liveness.mts,liveness/README.md,liveness/{seed,job,hook}.jsonbefore A
liveverdict needed only a consumer pointer.Seed.envwasliveon a correct one (filterByEnv) while none of the six call sites building aSeedLoaderRequestpassedenv— so the filter returned its input on its first line anddataset.envwas never read.seed-loader.test.tspassed throughout, because it suppliesconfig.envitself.after The criterion is written in the README: when a property's effect depends on a second input somebody must supply,
liverequires producer-side evidence. Newproducerfield, resolved through the same resolver asevidence(a repo-local path that does not exist fails CI). Absence never fails —check:liveness --producer-gapprints the worklist, and a table says which shapes actually need one. A malformed value fails, same asymmetry asverifiedAt. Six entries re-verified by hand:seed.env(restamped, both sides cited), andjob.timeout+hook.retryPolicy/timeout/onError— the same "read out of an options object built elsewhere" shape, checked and holding (the scheduler threads{retryPolicy, timeout}; the hook binder hands the authored hook to the wrapper). No mass re-grade, and no status flipped.3. #4895 — the #4667 liveness verdicts' cross-repo coverage
落点
producer.mts(evidenceScope),check-liveness.mts,liveness/README.md,liveness/{app,book}.jsonbefore Task 2 (the
homePageIdtombstone prose) landed in #4709. Tasks 1 and 3 were open: the #4667 batch had never been re-verified cross-repo, and no entry could say how wide its last look was.after New
evidenceScope: "in-repo" | "cross-repo", with the README recording the four measured blind-spot cases and the method they force (a negative cross-repo claim must follow the resolved symbol graph through re-export chains — case 4,Notification, proves no specifier match suffices). Task 1 done: all six keys of the #4667 batch re-verified against objectui @c2fd1223.app.homePageIdOuiAppSchema(pin test),AppPreviewignores it (pin test),resolveLandingRoute()documents the removal,RootLandingRedirectroutes onisDefaultapp.areas[].orderAppSchemaRenderer,AppSidebar,UnifiedSidebarall iterate array order and only filterbook.translations/book.groups[].translationsapps/console/src/pages/book-nav.ts) and neitherBooknorBookGroupdeclarestranslationsjob.idJobSchemaonly for client-side metadata-admin validation; no reader ofidtranslation.validationMessagesspec-translations.tstransports the key into the client i18n tree andTranslationPreviewechoes it, but nothing resolves it.translation.zod.ts:320already says exactly this — no correction owedNo counter-example found, which is the honest outcome of task 1 rather than a null result: the two surviving tombstone rows now carry
evidenceScope: cross-repoand the pinned commit. Task 3 is the field itself.⛔ Acceptance face — untouched
packages/spec/authorable-surface.base.jsonis byte-identical (no schema key added, removed or retired).check:authorable-surfacegreen. Three of the drift rows #6242 reports sit on acceptance faces (MetadataCategoryEnumdecides what a published artifact may declare); they are recorded as waivers with their reason rather than fixed, per the sweep's red line.Zero changes outside the member items
git diff --stat origin/main...HEAD, mapped 1:1:scripts/check-stack-collection-maps.mjs(new, +832)package.json(+1),.github/workflows/lint.yml(+12)packages/metadata/src/plugin.ts(+19/−4)data:removal + pin comment).changeset/stack-collection-maps-answerable.md(new)packages/spec/scripts/liveness/producer.mts+.test.ts(new)packages/spec/scripts/liveness/check-liveness.mts(+80)packages/spec/liveness/README.md(+100)packages/spec/liveness/{seed,job,hook}.jsonpackages/spec/liveness/{app,book}.json.changeset/liveness-producer-and-evidence-scope.md(new)Verification record
pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*', 70/70. Re-run after mergingorigin/main(the merge brought refactor(types,rest,metadata,analytics): Postgres"x" of relation "y"短语收归 @objectstack/types 一处 #7021, which moves a@objectstack/typesexport; a staledistmadepackages/restfail typecheck until the rebuild — not this diff).--filter '...pkg'(前缀)而非'pkg...'(后缀)—— 方向扫反会让「全绿」毫无意义(#6210 实测) #6218), stated direction: prefix —pnpm --filter '...@objectstack/spec' typecheck(everything that DEPENDS on spec, incl.packages/metadata,packages/objectql,packages/runtime,packages/rest,packages/qa/dogfood, all examples). Green.pnpm --filter @objectstack/spec exec tsc --noEmit— green.pnpm --filter @objectstack/spec exec vitest run scripts/liveness/— 8 files, 143 tests, green (8 new).node scripts/check-stack-collection-maps.mjs --self-test— 11 assertions over synthetic sources, both failure directions (unwaived deviation, stale waiver) driven.check:*gate enumerated from.github/workflows/lint.yml, one by one, not from memory — 46 root gates + 6 spec/lint-filtered (check:generated --reconcile-only,check:skill-docs,check:spec-changes,check:upgrade-guide,check:authorable-surface,check:doc-formula-expressions). All green.node scripts/check-adr-0087-registration.mjs --base origin/main— green (2 non-breaking changesets, no declared-breaking change).authorable-surface.base.json; no generated-products regeneration was triggered, so nothing undercontent/docs/referenceschanged.Coverage limit worth stating
cross-repohere means objectui only. Thecloudruntime is not reachable from an open-source checkout, so no verdict in this sweep claims coverage of it — the README says so where the value is defined, rather than lettingcross-reporead as "everywhere".Generated by Claude Code