Skip to content

[finding] spec-property-retirement SKILL.md tells a step-18 author to append to conversionIds and extend the rationale string: both change shape when PR #20572 lands #20575

Description

@objectstack-fleet

Blocked-by: #20535

Filing gate: ① a governed text that a landing makes false, with a named landing site. reach: every agent that follows the retirement playbook for a protocol-18 retirement. Governed surface (.claude/**), so the skills lane owns the edit.

Filed by the domain:spec execution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20535 dev report 5883564848 (out-of-scope finding 2). PR #20572 deliberately leaves the governed file untouched. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The Blocked-by: line is there because the text becomes false only when #20535's PR #20572 lands.

The text

.claude/skills/spec-property-retirement/SKILL.md:215-220 on origin/main, the "一步 D3 链" checklist item:

  • 「把 id 加进 MIGRATIONS_BY_MAJOR[N].conversionIds,扩写该步的 rationale」
  • the warning that a misspelled id is silently skipped at replay.

What changes when PR #20572 lands (for N = 18)

  • rationale is joinRationale(STEP18_RATIONALE): key-sorted fragments { id, order, text }. An author adds ONE fragment at its sorted id position, keyed by the retirement's D3 entry id, with its render order. Extending a concatenated string no longer exists.
  • conversionIds is derived: CONVERSIONS_BY_MAJOR[18]!.map(c => c.id). The author adds the conversion only to CONVERSIONS_BY_MAJOR[18]; there is no second list to edit.
  • For step 18, the "misspelled id silently skipped" failure mode no longer exists, since the ids come from the list itself. It still applies to earlier steps.

Suggested shape (⛔ not a ruling)

Reword the checklist item for step 18: add a fragment at its sorted position, add the conversion only to CONVERSIONS_BY_MAJOR[18], and the merge pin packages/spec/scripts/step18-rationale-merge.test.ts will refuse an unsorted append. Keep the old wording for earlier steps. If the sibling conversions-tail finding lands a keyed shape too, fold that wording in at the same time.

Dedupe words: spec-property-retirement rationale conversionIds step 18 · retirement playbook D3 chain wording


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: none — the retirement playbook says what the registry does | 缺项 (the step-18 checklist item has been false since PR #20572 landed) | P3

    Triage: first grade — documentation · priority:p3 · domain:skills · pm:queue. The body's blocker is already met

    Triage: lands in .claude/skills/spec-property-retirement/SKILL.md (:215–220), a governed surface (Tier H) ⇒ domain:skills.

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-29T06:07Z. ⛔ Not a claim, ⛔ not a dispatch.

    Not blocked. The body's Blocked-by: #20535 is met: #20535 closed completed, and PR #20572 merged at 2026-09-29T05:18Z. The step-18 item is false on main now: rationale is key-sorted fragments, and conversionIds is derived.

    Why p3. A governed playbook tells a step-18 author to edit a list that no longer exists. The merge pin refuses the wrong append loudly, so no one is silently misled. Every agent following the playbook meets the false line.

    Direction: as the card says.

  2. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_01KTZmMfzVzjNvyaLyQ8mHvg
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-20465-retirement-kit-routes
    Worktree: objectstack-issue-20465
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: family dispatch, member — folded into chain head #20465's dispatch (its claim carries the full serial-constraints reading and the fold answer). This card's part: .claude/skills/spec-property-retirement/SKILL.md the step-18 D3-chain item (:215–:220), worded for the shape on main after #20535 and #20574. The PR body carries one Fixes line per member and one commit per card.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate, the default judgment tier; reviewed at CONTRACT_REVIEW_TIER by an isolated at-tier subagent)
    Clause-②: no
    Thread-read: 5884681316
    Serial constraints cleared: see the chain head's claim on #20465 (one file, headroom 0, folded); #20535 and #20574 closed completed.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 20465,
    "members": [
    {
    "issue": 20575,
    "status": "done",
    "commit": "2e3f8aa0",
    "note": "Family member folded into this PR (one commit per card; the PR body carries its own Fixes line). Premise holds: on main after #20535 and #20574, step 18 conversionIds derive from CONVERSIONS_BY_MAJOR[18] = inApplicationOrder(MAJOR_18_CONVERSIONS), and rationale = joinRationale(STEP18_RATIONALE). The item is worded for that shape: the conversion goes only into MAJOR_18_CONVERSIONS at its identifier sort position, the rationale gains one STEP18_RATIONALE fragment at its D3 semantic id sort position, and the merge pins that each header names refuse a tail append. Earlier steps keep the old wording, and the misspelled-id warning is scoped to them."
    }
    ],
    "status": "done",
    "branch": "claude/issue-20465-retirement-kit-routes",
    "pr": "#20797",
    "session": "session_01KTZmMfzVzjNvyaLyQ8mHvg",
    "premise_still_valid": true,
    "summary": "Both cards landed as a draft family PR, #20797, head 2e3f8aa, two commits on base 7a09eee. (1) #20465, commit 249b783. The kit §2 route table and AGENTS.md Post-Task Checklist step 3 now say retiredKey() on any shape, strict or not. The strictObject guidance map is named only for a spelling the shape never declared (a retired key's old alias, a wrong-layer pointer), because there a tombstone has no property to replace; the example is data/mapping.zod.ts. The retiredFromLoadPath checklist item names the required retiredAfter stamp: tsc refuses its absence, a new retirement carries the current packages/spec label, and the census test pins each value. The ADR-0087 window bullet ("floor >= runtime replays nothing") is struck through and amended in the dated style, with provenance to the #20390 ruling A and e956924, and the status line gains an Amended entry. The sentence was false on main: idsTheFloorPostdates replays every retired entry whose retiredAfter the floor does not exceed, and 3 entries stamped 17.5.0 equal the label. (2) #20575, commit 2e3f8aa: the step-18 D3-chain item (see members). The label and PR-assignee write was refused by the session's permission classifier; see deviations. The seat must add skip-changeset and assign os-warren on #20797.",
    "tests": "Docs-only diff: no package test is owed. The one test that reads the kit, packages/spec/src/shared/retired-key-migrate-sentence.test.ts, was run under the verify lock at 2e3f8aa: 1 file and 14 tests passed, VERDICT command-exit 0. No ablation (no code changed).",
    "gates": "Derived by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at head 2e3f8aa against merge base 7a09eee: 3 paths, 31 families, the same set the dispatch named. Every one exited 0, with each exit code captured before any pipe: check-adr-0087-registration --base origin/main and --self-test; check-adr-links and --self-test (691 links resolve); check-adr-symbol-anchors and --self-test (2157 anchors across 140 records resolve); check-ci-filter-parity; check-closing-keyword-parity and --self-test; check-comment-mask-corpus; check-harness-current --self-test; pnpm check: adr-anchors, agent-test-spelling, changeset-gate-self-tests, cross-package-test-inputs, doc-authoring, docs-audit-scope, driver-memory-census, future-spec-major, gitlink-declared, nul-bytes, pm-governed-merges, pm-governed-prose, pm-prior-rulings, pm-skill-id-lint, pm-skill-ratchet, refd-timer-probe, required-contexts, skill-frame-sync, watch-hint-literal; pnpm --filter @objectstack/lint run check:doc-formula-expressions exited 0 on the re-run. Its first run exited 3 (PREREQUISITE NOT MET, formula and lint unbuilt), which measured nothing; turbo build of those two packages then ran under the verify lock (VERDICT command-exit 0). node scripts/pm/check-skill-line-ratchet.mjs exited 0. Reconciled with --ran: "31 derived, 31 run, 0 NOT-MEASURED, 0 UNRUN", a derived zero with every exit code recorded. The PR body closing keywords were checked with check-closing-keyword-parity --body: exactly Fixes #20465 and Fixes #20575 bind. CI: in_progress at report time; not waited on, per contract.",
    "line_budget": "check-skill-line-ratchet, exit 0. .claude/skills/spec-property-retirement/SKILL.md: 337/337 lines before and after (335 after commit 1); widest table row 326/326 before, 324/326 after (the ratchet prints an info hint to lower the pin to 324; the pin lives in scripts/pm/check-skill-line-ratchet.mjs, outside this surface, so it is left for the owning seat). Every added line is within 120 bytes except table rows (structurally exempt). New lines (+2 retiredAfter, +2 step-18) were paid by deleting narrative that is kept elsewhere: the orphan-leg history (-3, verbatim in the header of packages/spec/scripts/liveness/orphans.mts) and the withdrawn-example sentence in the retiredFromLoadPath item (-1, the rule it taught is the item's preceding sentence and the conversions/types.ts docblock). There was no re-wrap to buy lines and no ceiling change. AGENTS.md: 1106 to 1107 of 1116.",
    "files_changed": [
    ".claude/skills/spec-property-retirement/SKILL.md",
    "AGENTS.md",
    "docs/adr/0087-metadata-protocol-upgrade-contract.md"
    ],
    "deviations": [
    "Refused by the classifier, not retried: node scripts/pm/label-write.mjs --repo objectstack-ai/objectstack --issue 20797 --add skip-changeset --assign os-warren was denied by the session permission classifier (External System Writes) before any request was made. Neither the skip-changeset label nor the PR assignee is on #20797 (read back unauthenticated: labels [], assignees []). The seat writes both.",
    "Conflict with the triage wording, stated rather than chosen silently: the #20465 direction gives the guidance-map case "such as a z.preprocess stage ahead of the closed shape (retired-key.ts:177)". Measured, that example does not hold. retired-key.ts:177 is acceptRetiredDefaultResidue, whose closed shape still carries the retiredKey() tombstone behind the stage; the list view tabs tombstone (6e3e546) sits in a strict member of ViewMetadataSchema, which is itself a z.preprocess; and the guidance slot fires only on strictObject unrecognized_keys, so a preprocess stage cannot carry one either. Both texts instead name the measured case, a spelling the shape never declared (data/mapping.zod.ts query/onError, app.zod.ts showall/location). The PR body flags this for the maintainer's Tier H review.",
    "Surface: the claim named kit :86-:87, :207 and :215-:220. Consequential same-file edits: the ledger row and the ORPHAN bullet in §2 (:102, :107), and §4 :242 and :257. These are the term "strict 删除", which the new route table no longer names, renamed to "无墓碑删键". The payment deletions sit at the old :109-:112 and :213-:214. The AGENTS.md closing clause was reworded from "the two routes imply opposite liveness-ledger dispositions" to "a tombstone keeps its liveness-ledger row while a key deleted without one loses it", because the guidance-map route no longer deletes a key.",
    "The ADR-0087 half was amended (Zone 2 item 2 held), with a status-line Amended entry beside the in-body strike-through and amendment note, the same way ADR-0005 and ADR-0053 were amended.",
    "Commit trailers use the AGENTS.md model-free pair (Claude-Session, Co-authored-by: Claude). The harness reminder's model-named Co-Authored-By line was not used, because AGENTS.md says the pre-push hook refuses it; the pre-push check:commit-card-trailers passed.",
    "Cards were read through the public-page payload tier (#20465: totalCount 10 = edges 10, hasNextPage false; #20575: 11 = 11, false). The newest Claim: on each (5905577500, 5905586182) names this branch."
    ],
    "mcp_calls": "0",
    "api_writes": "1 relay dispatch at the time of this report: POST /repos/objectstack-ai/objectstack/dispatches (fleet-write run 36681600363, success), which executed pr_create POST /repos/objectstack-ai/objectstack/pulls (draft #20797). This os-dev-report comment pair travels in a second dispatch (comment on #20465 and on #20575). git push x2 (the empty-branch probe, then the two commits); these are not REST writes. The label-write was refused before any request (0 writes). Reads: unauthenticated public GETs (issue pages and PR JSON).",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: the next retirement-kit family card (this family's chain) or the domain:spec seat that owns packages/spec/scripts/build-schemas.ts, noted and not filed. Kit §3 still says to add the RETIRED_KEYS_BY_MAJOR entry "in packages/spec/src/migrations/registry.ts". Since #7297 the entry is one file under packages/spec/src/migrations/entries/retired-keys/ plus gen:migration-registry (entries/README.md, "never edit inside the markers"). The kit is echoing the build-schemas.ts gate (b) failure text, which still says to copy the key into registry.ts under the current major. That text is the producer. The failure is loud: check:migration-registry reds a hand edit. Same family as #20465 (governed retirement text naming a superseded mechanism). Dedupe words: RETIRED_KEYS_BY_MAJOR entry file, gate (b) message registry.ts, gen:migration-registry, retirement kit §3.",
    "carrier: none, noted and not filed. Kit §2 (the enum-value paragraph closing the four-ratchet subsection) prescribes a hand-rolled enum error map for an enum-value narrowing. retired-key.ts now carries the ruled generic helper enumWithRetiredValues() (#17109), with zero call sites; HookBodyCapability is still hand-rolled. This is dormant guidance drift with no author yet."
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #20797 @ 2e3f8aa0, family member (skills seat 1, session_01KTZmMfzVzjNvyaLyQ8mHvg, 2026-09-30T07:29Z)

    This card's half (the step-18 D3-chain item, commit on the family PR) is accepted with the family. The full ACCEPT, the review checklist and the Contract review PASS (5906291524) are on the chain head #20465; this comment is the pointer. Landing is Tier H: the maintainer's APPROVED review on PR #20797.


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Closed completed — skills seat 1, session_01KTZmMfzVzjNvyaLyQ8mHvg, 2026-09-30T08:53Z.

    Delivered by PR #20797 (family PR, chain head #20465), MERGED 2026-09-30T08:20Z as 4cc5bcd8.


    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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions