Repository navigation
docs(skills): teach that a save and os validate refuse titleFormat - #30096
Conversation
The objectstack-data properties table and the objectstack-formula template carriers now say the metadata save gate and os validate refuse titleFormat (title-format-retired) and that it moves to nameField. ADR-0079 D3 gains a dated amendment note citing ruling 6574393684 and PR #29499. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAkUoyAGLYtHWmyX2YW
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract-review-claim: session_01J8VVAnMUWA9rufXzFaEh4J · head c2236e3 · 2026-11-04T13:26Z The seat review runs at CONTRACT_REVIEW_TIER in an isolated subagent (the seat session is not at that tier). No review seat ( Generated by Claude Code |
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract reviewServed-tier: Reviewer: an isolated contract reviewer at CONTRACT_REVIEW_TIER, read-only on GitHub (REST reads only; nothing written, pushed or commented), fed the card body and comments, the PR body, the net diff against the merge-base, the head's check-runs, AGENTS.md, the pm-dispatch SKILL.md contract-review section, contract-review.md, review-checklist.md, lanes/skills.md and lanes/review.md. The dev gate record was read as input, not as conclusions; every count and every claim about the lint rule, the save gate and the ADR below is this review's own reading of the head tree and of ① Derived judgments
② Semver levelPatch, and the changeset says patch. ③ Boundary flags
④ Design judgmentPer hits file, against the card's scenario (an author or agent reading the skill must learn that a save and
Must-fix: none. Should-fix: S1 — three edits in the ADR, all prose, no decision touched: (a) in the amendment, "only the 'advisory, not an error' sentence and its citation" → "the 'deprecated and lint-warned' and 'advisory, not an error' sentences and their citation"; (b) a one-line note under the D8 heading, Check-runs at record time (2026-11-04T13:39Z): 42 check-runs on c2236e3, 28 success, 13 skipped, 0 failure, 1 in progress on the second read (Test Core 1/8); two reads went 27 → 28 success and 2 → 1 in progress (Test Core 2/8 completed success between them) with no non-success completion at either read. Success: Lint & Repo Gates, TypeScript Type Check (the two required floors), Lint · repo & tooling gates, Lint · CI, release & engine gates, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · ESLint, Lint · scoped · tooling self-tests, Lint · scoped · slot lookup & corpus, Lint · scoped · query-options erasure, Type Check · workspace / source gates / debt ledger / consumer gates, Build Core, Governed Surface Queue Guard, Dogfood Regression Gate, Test UI, Test Core (2/8), Test Core (3/8), Plan Test Core shards, Live E2E UI, PR-body guards, Check Changeset, Check Documentation Links, Check PR Size, Auto Label, filter. Skipped by path filter or opt-in: Build Docs, Build UI Deps, Build & E2E UI, Lint UI, Type Check UI, UI Published Artifacts, Dogfood Verify CLI, Temporal Conformance, Schedule gate, 18.x upgrade harness, Packed-tarball smoke, and the matrix-templated placeholder rows for Test UI and the Dogfood shards. Combined status Implemented-by: VERDICT: PASS Generated by Claude Code |
The D3 note now names both pre-refusal sentences, D8 carries a pointer back to it, and the status line records the amendment. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8VVAkUoyAGLYtHWmyX2YW
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract-review-claim: session_01J8VVAnMUWA9rufXzFaEh4J · head f27efd1 · 2026-11-04T13:52Z The seat delta review (against 6632133331 S1 and S2) runs at CONTRACT_REVIEW_TIER in an isolated subagent (the seat session is not at that tier). No review seat ( Generated by Claude Code |
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J Contract reviewServed-tier: Reviewer: the same isolated contract reviewer at CONTRACT_REVIEW_TIER, read-only on GitHub (REST reads only; nothing written, pushed or commented). The full review on c2236e3 (PASS, should-fixes S1 and S2) stands as read; this record judges only the delta ① Derived judgments
② Semver levelUnchanged: patch, and the changeset still says patch. The delta is prose in an ADR, which publishes nothing; ③ Boundary flags
④ Design judgmentPer hits file, for the delta only:
Must-fix: none. Should-fix: none remaining — S1 (a, b, c) and S2 of 6632133331 are all resolved on this head. Check-runs at record time: 46 check-runs on f27efd1, 30 success, 15 skipped, 0 failure, 1 in progress (Test Core 1/8) on both reads; combined status Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J 维护者速读
席位核对 — ACCEPT · domain:skills#1 · head
|
domain:skills#1 · huangyiirene · session_01J8VVAnMUWA9rufXzFaEh4J
Requested by Irene · project thread
Fixes #29506
Clause-②: no
Metadata-protocol: none
The maintainer waived the model-tier mandate for
skills/**while that tier had no quota; this PR was developed below it.维护者速读
titleFormat讲成「已弃用但未移除」,改为「保存和os validate会拒绝它(title-format-retired),改用nameField」;ADR-0079 D3 加一条带日期的修订说明,引用裁决 6574393684 和 PR feat(spec)!: refuse an object that declares titleFormat at save and os validate, with the nameField prescription #29499。决定本身不动。os validate拒绝写了titleFormat的对象,三处文本还在教旧规则(「advisory, not an error」)。skills/objectstack-data/SKILL.md的titleFormat行;docs/adr/0079-record-display-name.mdD3 下的 Amendment 块。skills/**),契约复审后需要GOVERNED_APPROVERS批准;PR 保持 draft。What changes
The refusal is read off main, not the card:
packages/lint/src/validate-record-title.ts(validateTitleFormatRetired, severityerror, ruletitle-format-retired, registered inauthoring-rules.tswithsurfaces: CLI_AND_RUNTIME) andpackages/spec/src/migrations/entries/semantic/18.object-title-format-refused.ts("os validate,os build,os lintand the metadata save gate (422 INVALID_METADATA) refuse the key astitle-format-retired, an error").skills/objectstack-data/SKILL.md, thetitleFormatrow of the optional-properties table:**Deprecated, not removed (ADR-0079)** — render-only: the server can't return or query it. UsenameField(it wins); a composite title follows thenameFieldrow**Refused (ADR-0079)**: a save andos validaterefuse it (title-format-retired). Move it tonameField; a composite title follows thenameFieldrowos explain title-format-retired(the lint fix line points there,validate-record-title.ts[[maintainer] validate: thefield-no-consumerswarning is one 856-character line, printed by validate, build and dev alike — one-line verdict +rule:id + a pointer to the full reasoning (os explain, which today takes only schema names) #22161] comment) and ADR-0079 D3. "(it wins)" is dropped because precedence no longer matters once the key is refused.skills/objectstack-formula/SKILL.md, thetemplaterow's carriers cell:Object.titleFormat(deprecated →nameField, ADR-0079) becomesObject.titleFormat(a save andos validaterefuse it; move it tonameField, ADR-0079). Paid by deleting the sentence below the table "a template holds a path and a formatter, nothing else.", which restates the same row's Grammar cell ({{ path }}or{{ path | formatter[:arg] }}, no conditionals). "Move logic into a CEL field" stays; the two lines around the cut are otherwise byte-identical, no re-wrap.docs/adr/0079-record-display-name.md: a dated amendment block directly under the D3 heading, citing ruling 6574393684 (object.titleFormat has no effect when the object authors no nameField: the registry stamps a derived nameField that outranks the template, so the record title ignores it #29007, letter B) and PR feat(spec)!: refuse an object that declares titleFormat at save and os validate, with the nameField prescription #29499 (3557366c02). It says the key is refused, not removed (the schema still parses it, so a stored object keeps loading until its next save), which keeps the wording consistent with Open question 3's remark that "retired" is used for a key that is still live. It names the "deprecated and lint-warned" and "advisory, not an error" sentences as describing the code before feat(spec)!: refuse an object that declares titleFormat at save and os validate, with the nameField prescription #29499, and notes D8's "never errors" no longer coverstitle-format-retired. D8 carries a one-lineAmended (2026-11-04, #29506)pointer back to the D3 note (D8's own text is unchanged), and the status line gains· **Amended** (2026-11-04, #29506, ruling 6574393684 …)in the ADR-0045 form. D3's decision and its quoted citation are left as they are..changeset/29506-title-format-refused-teaching.md:'@objectstack/skills': patch, withClause-②: noandMetadata-protocol: none.Token ratchet (no ceiling row moved, no re-wrap)
skills/objectstack-data/SKILL.mdskills/objectstack-formula/SKILL.mdWhy
PR #29499 made a save and
os validaterefuse an authoredtitleFormat(ruling 6574393684). The skills still taught "deprecated, not removed" and the ADR still said "advisory, not an error", so an author following them would write a key the platform refuses.Verification
Head
f27efd1d(two commits ond79eecfe:c2236e37, then the S1 ADR follow-up).Local gates on f27efd1 (and on c2236e3 before it): 50 derived, 50 run with exit 0, 0 NOT MEASURED (`dispatch-gates --ran`)
pnpm install --frozen-lockfileand a fullpnpm build(exit 0) ran first (on c2236e3; f27efd1 touches only the ADR, so the build was reused), then every command fromnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, each with a 900 s timeout and its exit code captured before any pipe.check-skills-token-ratchet.mjs(and--self-test),check-adr-links.mjs,check:adr-anchors,check:adr-index,check:adr-symbol-anchors,check-changeset-no-major.mjs,check-empty-changeset.mjs,check:changeset-gate-self-tests,check-comment-mask-corpus.mjs,check:corpus-claim-drift,check:cross-package-test-inputs,check:doc-authoring,check:doc-formula-expressions,check:skill-docs,check:skill-identifier-liveness,check:skill-frame-sync,check:skill-compatibility,check:dts-closure,check:dual-build-cjs-loadsandcheck:role-word.--ranprinted:50 derived famil(ies) accounted for — 50 run, 0 NOT-MEASURED.node scripts/check-commit-card-trailers.mjs --range origin/main..HEAD: exit 0.git push(c2236e3, f27efd1); one relaypr_create; no GitHub MCP write.Human Minimum
packages/specholds no runtime logic. (No schema touched.)pnpm lintis CI's repo-wide run.main, one pull request.packages/specnot touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.🤖 Generated with Claude Code
https://claude.ai/code/session_01J8VVAkUoyAGLYtHWmyX2YW