Repository navigation
spec(api): RuntimeAuthoringIssueSchema.path's describe names object / permission / book as the only name-keyed write types and calls every other type positional, but a dataset write's findings are name-keyed since #19143 #22759
Description
Activity
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsTriage: first grade,
documentation·priority:p3·domain:spec·area:api, kept inpm:queueTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-11T04:59Z. ⛔ Not a claim, ⛔ not a dispatch.- Lane: a describe string in
packages/spec/src/api/protocol.zod.tsisdomain:spec. - Why p3: a published describe understates which write types are name-keyed. No answer is wrong.
- Direction, as filed: state the rule (the top-level entry of a collection-resident write type is keyed by name) rather than a closed list. Regenerate the references.
Clause-②: no. - It was filed under ruling
6104584601on lint(runtime gate): a flow write's per-write snapshot carries no actions and no other flows, so a flow CEL root rule cannot see the entrances that hand a flow its record (W, from #22565) #22636, so it enters the queue as maintainer-directed text.
- Lane: a describe string in
- addedarea:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsThe API a customer can call, and integrations — REST, connectors, webhooks, jobsdocumentationImprovements or additions to documentationImprovements or additions to documentation
on Oct 11, 2026 objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsClaim: PM loop round 8 (#22759:
RuntimeAuthoringIssueSchema.path's describe states the name-keyed rule for every collection-resident write type, per triage's grade6105640249) · 2026-10-11T06:07Z
Session:session_01KNKBCRDJCu5tGy3TEbvtrF
Account:zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22759-issue-path-name-keyed
Worktree:objectstack-issue-22759
Domain:domain:spec
Seat:domain:spec#3(seat post #18883)
File surface (atorigin/maine84aeb36ce; stop on breach and explain in the report):packages/spec/src/api/protocol.zod.ts: theRuntimeAuthoringIssueSchema.pathdescribe (about:560–:571). Describe text only.- Any other shipped describe or JSDoc in
packages/specthat repeats the same closed list of name-keyed write types: same defect, same fix, listed in the PR body. Anything outsidepackages/spec: stop and report. - The generated references, as
check:generated/check:docsdecide (content/docs/references/api/protocol.mdxcarries the text three times ate84aeb36ce). .changeset/22759-*.md:@objectstack/specpatch,Clause-②: no.
Container & model:S,mode:subagent,model: default tier(dispatch-gates --tier: no path-derived mandate; the wording states a rule, a judgement call). A describe string: the accept set does not move. Before enqueue, an at-tier review (CONTRACT_REVIEW_TIER) confirms that.
Clause-②: no
Responsibility: n/a — not a defect card (a shipped-text correction)
Thread-read: 6105640249
Serial constraints cleared:- No open PR touches
packages/spec/src/api/protocol.zod.tsorcontent/docs/references/api/protocol.mdx. Two open PRs touchpackages/spec/src/api/error-code-ledger.zod.tsonly (feat(plugin-security,rest,spec)!: retire the permission-set overlay discard (ADR-0131 cutover stage 7-pre) #22776, fix(metadata-protocol)!: a nested-relation filter condition asks the related object its declared exposure (#22737) #22768). This reading covers every open PR's file list, read at 2026-10-11T06:07Z. - No live
Claim:on apm:dispatchedcard names either file. security(data): a nested-relation filter condition on a lookup target is evaluated without asking the target's exposure (census row 4 of #22661) #22737's claim nameserror-code-ledger.zod.tsonly. area:api: no other card of this seat is in flight on the axis.
This act moves the card
pm:queue→pm:dispatchedand assignszhuangjianguo.
Generated by Claude Code
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22759,
"status": "done",
"branch": "claude/issue-22759-issue-path-name-keyed",
"pr": "#22784",
"session": "session_01KNKBCRDJCu5tGy3TEbvtrF",
"premise_still_valid": true,
"summary": "The RuntimeAuthoringIssueSchema.path describe (packages/spec/src/api/protocol.zod.ts) now states the rule instead of a closed list. A write type is collection-resident when the gate's private per-write snapshot fills its collection with the tenant's other stored items beside the written one, and there the top-level entry is keyed by NAME. Every other write type is the sole member of its collection, so its [0] stays positional. The members are derived, never listed: the text names @objectstack/lint's runtime gate (NAME_KEYED_STACK_KEYS) and the derivation in prose. Its only named members are two examples marked 'for example' (object, dataset). The submitted-body framing, the empty path and the positional nested positions are kept. One true sentence is added: an entry whose name cannot be spliced into a dotted path keeps its index (the nameKeyFindingPath fallback); without it 'never by an array index' is false. Describe text only. The generated api/protocol.mdx is regenerated with gen:docs (3 occurrences), and a patch changeset is added for @objectstack/spec with Clause-②: no. Draft PR 22784, assignee zhuangjianguo.",
"tests": "All runs at head 498abe7. (1) pnpm --filter @objectstack/spec build, under the lock: VERDICT command-exit 0. (2) check:generated before regeneration: exit 1, '1 of 14 artifact(s) stale: content/docs/references/**'. gen:docs: exit 0, only api/protocol.mdx changed (+3/-3). After: check:generated exit 0, 'All 14 generated artifacts are up to date'. check:docs exit 0, '225 generated files in sync with packages/spec'. (3) pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2, under the lock: 'Test Files 645 passed (645)', 'Tests 19222 passed | 1 todo (19223)', VERDICT command-exit 0. (4) pnpm --filter @objectstack/spec typecheck, under the lock: VERDICT command-exit 0. check:test-typecheck OK, 52 files / 246 errors / 135 pinned signatures held. (5) Premise pins, after pnpm --filter @objectstack/lint build: vitest run on runtime-gate.dataset-writes.test.ts and runtime-gate.derived-name-keys.test.ts, 'Test Files 2 passed (2)', 'Tests 29 passed (29)'. (6) Probe driving buildRuntimeWriteSnapshots and nameKeyFindingPath from packages/lint/src: derived set objects,permissions,books,datasets. 17 gated write types; 4 name-keyed, 13 positional with 1 member each. No ablation or reverse verification: the change is describe text, with no type or behaviour to invert.",
"mcp_calls": "0 — no MCP GitHub tool was called. Reads went through gh api (REST GET).",
"api_writes": "3 relay strokes, each one repository_dispatch (HTTP 204) executed by the fleet-write workflow as objectstack-fleet[bot]. (a) pr_create: POST /repos/objectstack-ai/objectstack/pulls, draft, run 38118615577, body read back byte-identical (7270 bytes). (b) label-write --assign: POST /repos//issues/22784/assignees, run 38118648868, read back assignees zhuangjianguo, labels untouched. (c) post-stamped --comment=22759: POST /repos//issues/22759/comments, this report. Plus git push (not REST): the empty branch probe and 2 commits.",
"open_questions": [],
"out_of_scope_findings": [],
"gates": "No-path dispatch-gates --commands --repo objectstack-ai/objectstack at 498abe7: 3 paths, 103 commands. Reconciled with --ran: '103 derived, 100 run, 2 NOT-MEASURED, 1 UNRUN'. 100 green, 4 of them after a rerun: check:doc-formula-expressions and check:doc-security-posture first exited 3 because lint was not built, check:docs-transcript-drift exited 3 for the same reason, and check:dts-closure ran while my lint build was rewriting its dist. All 4 were green once lint was built. NOT MEASURED (exit 3, prerequisite): check:skill-examples needs client-react built; check:lean-entry-closure needs objectql built. Both closures are outside this diff, so both are left to CI. UNRUN: check:dual-build-cjs-loads, by dispatch (no whole-workspace build). check:type-check-debt was not derived. Artifact rosters block (50): 49 green, 1 NOT MEASURED. The PR-context guards ran wired to PR 22784: check-closing-target-claim exit 0 ('PR 22784 closes 22759, and each carries a Claim whose Branch line names claude/issue-22759-issue-path-name-keyed'), check-partof-closing-keyword exit 0, check-single-claim-paths exit 0 (wired rerun; the unwired first pass exited 2). check:published-readme-exports is NOT MEASURED: exit 3, 44 packages unbuilt. check-closing-keyword-parity --body on the PR body binds #22759 only, as intended. CI convergence not awaited.",
"line_budget": "n/a — no governed or skills surface touched (packages/spec/src, content/docs/references, .changeset only).",
"deviations": [
"The describe gains one sentence beyond the rule ('an entry whose name cannot be spliced into a dotted path keeps its index'). It is the nameKeyFindingPath fallback (runtime-gate.ts:945), and 'never by an array index' is false without it. Still describe text only, with no shape change.",
"scripts/pm/os-regen-merge.sh exited 1: 'HEAD already contains origin/main and NO pre-merge base is recorded'. origin/main had not moved from the base e84aeb3 (merge-base --is-ancestor origin/main HEAD exit 0, self-proving), so there was nothing to merge. The script says the refusal is then the whole outcome.",
"Built packages outside the diff for measurement only: @objectstack/formula and @objectstack/sdui-parser, so the probe could import lint src; and @objectstack/lint, which the probe pins and three lint-reading gates need. No source outside the diff changed.",
"Commit trailers use AGENTS.md's model-free pair (Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By. The PR footer uses AGENTS.md's session-URL form instead of the reminder's form. AGENTS.md takes precedence by the reminder's own words.",
"PR labels documentation, size/s and tooling were applied by other actors (labelers) after pr_create. I wrote no label, as dispatched.",
"No spec pin was added for the describe; the PR body gives the reason. The text carries no enumeration that can drift, and the derived set is already pinned in lint's derived-name-keys test."
],
"files_changed": [
"packages/spec/src/api/protocol.zod.ts (the RuntimeAuthoringIssueSchema.path describe, +19/-9)",
"content/docs/references/api/protocol.mdx (generated by gen:docs, +3/-3)",
".changeset/22759-runtime-authoring-issue-path-rule.md (new, @objectstack/spec patch, Clause-②: no)"
],
"zone2_readings": {
"1_text": "Confirmed at e84aeb3, protocol.zod.ts:560-571: 'For the collection-resident write types (object/permission/book) the TOP-LEVEL collection entry is keyed by NAME (objects.acme_invoice.sharingModel), never by an array index ... Every other write type is the sole member of its own collection, so its[0]is trivially stable and stays positional (flows[0]...)'.",
"2_truth": "runtime-gate.ts:905 NAME_KEYED_STACK_KEYS = deriveNameKeyedStackKeys(CONTEXT_STACK_KEYS :550, WRITTEN_STACK_KEYS :845), giving objects, permissions, books, datasets. The write types that map into those keys (TYPE_TO_STACK_KEY :94; dataset at :146) are object, permission, book and dataset. page is NOT in the set: the lint CHANGELOG.md:5287 records pages joining it, but pages left with the context when validateViewPageRefs was retired (derived-name-keys.test.ts:53-68 pins the four and records the exit). Pins confirmed green: dataset-writes.test.ts:310 expects datasets.acme_invoice_metrics.dimensions[0].field and :313 refuses datasets[N]; derived-name-keys.test.ts:85 checks each context collection.",
"3_sole_member": "True for every one of the 17 gated write types (the union of runtimeTypes over AUTHORING_RULES). The candidate snapshot has 1 member for action, app, dashboard, datasource, email_template, flow, hook, mapping, page, position, report, seed (key data) and view, all positional. object, permission, book and dataset have the stored siblings plus the item, and are name-keyed. agent is mapped but ungated.",
"4_family": "packages/spec: one hit, this describe, edited. packages/spec/CHANGELOG.md:31982 is the released def0d3e entry, release-owned and accurate for its time, not edited. Generated: api/protocol.mdx :2371/:2597/:2651, regenerated (the card's :2349/:2575 had shifted). Outside spec, reported only, none wrong: lint runtime-gate.ts:612-617 already names dataset; validate-security-posture.runtime-surface.test.ts:168 is a historical note; authoring-rules.ts:202, data-model-rules.ts:66 and bench runtime-publish-gate.bench.mts:495 use an example, not a list."
}
}objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actions✅ ACCEPT — PR #22784 at
498abe794e. Next: the at-tier review on this headdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-11T06:42Z · holder of claim6106102177. Thread-read: 6106333502.Read in the diff (
origin/main...498abe794e: 3 files, +35 / −12):packages/spec/src/api/protocol.zod.ts: theRuntimeAuthoringIssueSchema.pathdescribe, and nothing else. It no longer listsobject/permission/book. It now states the rule: a write type is collection-resident when the gate's per-write snapshot fills its collection with the tenant's other stored items beside the written one, and there the top-level entry is keyed by name.- The two named members are examples, marked as such:
object, anddatasetwith the card's own path. - It points at the derived set in
@objectstack/lint's runtime gate, in prose. It does not import it. - It keeps the submitted-body framing, the empty path and the positional nested positions.
- The two named members are examples, marked as such:
content/docs/references/api/protocol.mdx: regenerated bygen:docs, +3 / −3, the three occurrences..changeset/22759-runtime-authoring-issue-path-rule.md:@objectstack/specpatch,Clause-②: no.
The text checked against
origin/maine84aeb36ce(the seat's own reading ofpackages/lint/src/runtime-gate.ts):NAME_KEYED_STACK_KEYS(:905) isderiveNameKeyedStackKeys(CONTEXT_STACK_KEYS, WRITTEN_STACK_KEYS)(:796). It keeps the context collections that a mapped write type also lands in, which is the describe's wording.runtime-gate.derived-name-keys.test.tspins the set toobjects,permissions,books,datasets.pagesleft withvalidateViewPageRefs(spec: retire thepagemember of the list-viewtypeenum and itspageNamemount — enforce-or-remove, the objectui render half was never built (maintainer 2026-09-09 「撤」) #17063). The card's suggestion thatpageis a member is wrong, and the dev's reading is right.datasetsarrived by derivation ([finding] a runtime-createddatasetreaches ZERO author-time rules — the type declaresallowRuntimeCreate: truewhile nothing declares it inruntimeTypesandTYPE_TO_STACK_KEYhas no row #19143).
- The added sentence, "an entry whose name cannot be spliced into a dotted path keeps its index", is
nameKeyFindingPath(:945). It returns the path unchanged when the entry'snameis not a string or failsPATH_SAFE_NAME. Without the sentence, "never by an array index" would be false. Accepted as a deviation inside the describe.
Measurements accepted:
- The spec suite: 645 files and 19222 tests, plus typecheck with
check:test-typecheckOK. - Generated checks:
check:generatedred beforegen:docsand green after;check:docs225 in sync. - The lint pins: 2 files and 29 tests.
- The probe: 17 gated write types; 4 name-keyed and 13 positional with one member each.
- Gates: 103 derived, 100 run and green. NOT MEASURED:
check:skill-examples,check:lean-entry-closure(prerequisite builds outside the diff) andcheck:published-readme-exports. UNRUN by dispatch:dual-build-cjs-loads. The PR-context guards were run wired to PR docs(spec): RuntimeAuthoringIssueSchema.path states the name-keying rule for every collection-resident write type #22784 and are green. - No pin and no ablation: the change is describe text, with no behaviour to invert. The text carries no enumeration that can drift, and the lint pin holds the set. Accepted.
Out-of-scope findings: none. The family sweep found one hit in
packages/spec, this describe. The hits outside are examples or history, none false.The claim promised an at-tier review (
CONTRACT_REVIEW_TIER) before enqueue, confirming that the accept set does not move. It follows on498abe794e.
Generated by Claude Code
objectstack-fleet commented
on Oct 11, 2026 ContributorAuthorMore actionsLanded: PR #22784 →
322ff1ebb4(Fixes #22759). The card is closed as completeddomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-11T08:02Z · holder of claim6106102177.-
Landed: through the merge queue at 2026-10-11T08:01Z as
322ff1ebb4, a squash with one parent,680a86b4c5. The queue did not eject it. -
The review chain: the ACCEPT
6106348302, the contract review PASS6106409844at498abe794e, and the pre-queue record6106735168. -
Content check: all 3 PR paths on
322ff1ebb4are blob-equal to the reviewed head498abe794e. -
What now holds: the
RuntimeAuthoringIssueSchema.pathdescribe, as it ships in the JSON schema andcontent/docs/references/api/protocol.mdx, states the rule instead of a list:- a write type whose collection the gate's per-write snapshot fills with the tenant's other stored items is keyed by name;
- every other write type stays positional;
- an entry whose name cannot be spliced into a dotted path keeps its index.
The named members (
object,dataset) are examples. The set lives in@objectstack/lint's runtime gate, derived and pinned there. -
Carried: the review's boundary flag stays an acceptance note. The describe names
NAME_KEYED_STACK_KEYS, an unexportedconstinpackages/lint/src/runtime-gate.ts, and a rename there would leave the sentence stale. No card is filed: the derivation's own pin (runtime-gate.derived-name-keys.test.ts) is the place a rename is read. -
Mis-close scan: the squash message carries
Fixes #22759alone, and the merge closed spec(api):RuntimeAuthoringIssueSchema.path's describe namesobject/permission/bookas the only name-keyed write types and calls every other type positional, but adatasetwrite's findings are name-keyed since #19143 #22759 alone. skills(objectstack-data):rules/field-types.mdsays a formula'sreturnTypehas nocurrencymember, which PR #22733 (#22727) widens #22743 and skills+docs: governed texts still describe the committed spec-changes.json, its os-regen route and its regeneration lap, which #22485 (PR #22638) retired #22667, closed in the same queue batch, are PRs docs(skills): field-types rule states a formula's fivereturnTypemembers and thecurrencyConfiga currency formula carries (#22743) #22798's and docs(governed): ADR-0087, AGENTS.md and the retirement playbook describe the D4 projections and the migration registry as main builds them #22796's own closing targets.
This act removes
pm:dispatched; the domain, priority and area labels stay.
Generated by Claude Code
-
Filing gate ①: a shipped-text defect with a named producer and a reproduction. Filed by
domain:specseat 2 (#18549) ·marchtian· sessionsession_016njDy8ozy9B9Ns5Y8kAWEK, as ruling6104584601on #22636 directs: "The seat's note that thepathdescription omits datasets (named since #19143) is a separate spec card the seat files." The finding was measured by #22636's dev (os-dev-report6102874585, out-of-scope finding 1). ⛔ Not a claim.Acting reader: the
domain:speclane (triage grades it). The fix is apackages/specdescribe-only PR.Reach
A named producer:
packages/lint/src/runtime-gate.tsnameKeyFindingPath(about:945) feeds the runtime publish gate'stoIssueunchanged. Its output is theissues[].pathof the 422 adatasetsave answers.The pin
packages/lint/src/runtime-gate.dataset-writes.test.ts:310expectsdatasets.acme_invoice_metrics.dimensions[0].field, and:313refuses a positionaldatasets[N].What is false (read on
origin/mainat filing)packages/spec/src/api/protocol.zod.tsabout:560–:571, theRuntimeAuthoringIssueSchema.pathdescribe:object/permission/book) the TOP-LEVEL collection entry is keyed by NAME";[0]is trivially stable and stays positional".Since [finding] a runtime-created
datasetreaches ZERO author-time rules — the type declaresallowRuntimeCreate: truewhile nothing declares it inruntimeTypesandTYPE_TO_STACK_KEYhas no row #19143, adatasetwrite is collection-resident too, and its findings are name-keyed.This is release text: the describe ships in the generated JSON schema and in
content/docs/references/api/protocol.mdx(:2349and:2575, both generated).Done when
NAME_KEYED_STACK_KEYSmakes name-keyed. Better, it states the rule (the top-level entry of a collection-resident write type is keyed by name) without a closed list that drifts again.gen:docs), withcheck:docsandcheck:generatedgreen.Clause-②: no(a describe string; the accept set does not move). Apatchchangeset for@objectstack/spec.Dedupe: an MCP
search_issueson this repo,RuntimeAuthoringIssueSchema path name-keyed dataset collection-resident write types describe positional, returned 1 hit (#6234, closed, unrelated).Generated by Claude Code