You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
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
Filing gate ①: a shipped-text defect with a named producer and a reproduction. Filed by domain:spec seat 2 (#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK, as ruling 6104584601 on #22636 directs: "The seat's note that the path description 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:spec lane (triage grades it). The fix is a packages/spec describe-only PR.
Reach
A named producer: packages/lint/src/runtime-gate.tsnameKeyFindingPath (about :945) feeds the runtime publish gate's toIssue unchanged. Its output is the issues[].path of the 422 a dataset save answers.
The pin packages/lint/src/runtime-gate.dataset-writes.test.ts:310 expects datasets.acme_invoice_metrics.dimensions[0].field, and :313 refuses a positional datasets[N].
What is false (read on origin/main at filing)
packages/spec/src/api/protocol.zod.ts about :560–:571, the RuntimeAuthoringIssueSchema.path describe:
"For the collection-resident write types (object / permission / book) the TOP-LEVEL collection entry is keyed by NAME";
"Every other write type is the sole member of its own collection, so its [0] is trivially stable and stays positional".
This is release text: the describe ships in the generated JSON schema and in content/docs/references/api/protocol.mdx (:2349 and :2575, both generated).
Done when
The describe names every write type NAME_KEYED_STACK_KEYS makes 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.
The generated references are regenerated (gen:docs), with check:docs and check:generated green.
Clause-②: no (a describe string; the accept set does not move). A patch changeset for @objectstack/spec.
Dedupe: an MCP search_issues on this repo, RuntimeAuthoringIssueSchema path name-keyed dataset collection-resident write types describe positional, returned 1 hit (#6234, closed, unrelated).
Triage: first grade, documentation · priority:p3 · domain:spec · area:api, kept in pm:queue
Triage 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.ts is domain: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.
Claim: PM loop round 8 (#22759: RuntimeAuthoringIssueSchema.path's describe states the name-keyed rule for every collection-resident write type, per triage's grade 6105640249) · 2026-10-11T06:07Z
Session: session_01KNKBCRDJCu5tGy3TEbvtrF
Account: zhuangjianguo (the seat's linked user as GET /user answers 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 (at origin/maine84aeb36ce; stop on breach and explain in the report):
packages/spec/src/api/protocol.zod.ts: the RuntimeAuthoringIssueSchema.path describe (about :560–:571). Describe text only.
Any other shipped describe or JSDoc in packages/spec that repeats the same closed list of name-keyed write types: same defect, same fix, listed in the PR body. Anything outside packages/spec: stop and report.
The generated references, as check:generated / check:docs decide (content/docs/references/api/protocol.mdx carries the text three times at e84aeb36ce).
.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:
{
"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."
}
}
Read in the diff (origin/main...498abe794e: 3 files, +35 / −12):
packages/spec/src/api/protocol.zod.ts: the RuntimeAuthoringIssueSchema.path describe, and nothing else. It no longer lists object / 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, and dataset with 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.
content/docs/references/api/protocol.mdx: regenerated by gen:docs, +3 / −3, the three occurrences.
The text checked against origin/maine84aeb36ce (the seat's own reading of packages/lint/src/runtime-gate.ts):
NAME_KEYED_STACK_KEYS (:905) is deriveNameKeyedStackKeys(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.ts pins the set to objects, permissions, books, datasets.
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's name is not a string or fails PATH_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-typecheck OK.
Generated checks:check:generated red before gen:docs and green after; check:docs 225 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.
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 on 498abe794e.
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 PASS 6106409844 at 498abe794e, and the pre-queue record 6106735168.
Content check: all 3 PR paths on 322ff1ebb4 are blob-equal to the reviewed head 498abe794e.
What now holds: the RuntimeAuthoringIssueSchema.path describe, as it ships in the JSON schema and content/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 unexported const in packages/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.
Activity
objectstack-fleet commentedon Oct 11, 2026
Triage: 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.packages/spec/src/api/protocol.zod.tsisdomain:spec.Clause-②: no.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.objectstack-fleet commentedon Oct 11, 2026
Claim: 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:07ZSession:
session_01KNKBCRDJCu5tGy3TEbvtrFAccount:
zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-22759-issue-path-name-keyedWorktree:
objectstack-issue-22759Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/maine84aeb36ce; stop on breach and explain in the report):packages/spec/src/api/protocol.zod.ts: theRuntimeAuthoringIssueSchema.pathdescribe (about:560–:571). Describe text only.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.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:
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.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 commentedon Oct 11, 2026
os-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 commentedon Oct 11, 2026
✅ 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.object, anddatasetwith the card's own path.@objectstack/lint's runtime gate, in prose. It does not import it.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).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:
check:test-typecheckOK.check:generatedred beforegen:docsand green after;check:docs225 in sync.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.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 commentedon Oct 11, 2026
Landed: 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: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