Skip to content

[finding] 8 residual #12081-class soft breaks remain in .claude/agents/os-dev.md — each renders as a stray mid-sentence space in the file every dispatched dev reads #12891

Description

@os-litant

Recording only — unassigned. Measured while landing the skip-changeset-at-birth edit
(PR #12890, 2026-08-28), on a tree at 8b02f78c7.

The measurement

check-skill-line-ratchet.mjs refuses to OFFER a break directly after an ASCII , ; :
that follows a Han character (hanAsciiPunctTail), because such a break is not between two
wide characters and so survives the CSS segment-break transformation — it renders as a
space, mid-sentence, in prose that has no spaces anywhere else. That channel was shut at
its source, and the pre-existing breaks were left to be paid down opportunistically, file
by file (the ceiling comment on references/decision-analysis.md records three of them
merging back).

.claude/agents/os-dev.md still carries 8, at lines 15, 32, 87, 99, 245, 356, 361, 454
(post-PR-12890 numbering). Reproduce:

node -e 'const fs=require("node:fs");const HAN=/\p{Script=Han}/u;
const L=fs.readFileSync(".claude/agents/os-dev.md","utf8").split("\n");
const out=[];for(let i=0;i<L.length-1;i++){const t=L[i],a=t[t.length-1],b=t[t.length-2];
if(/[,;:]/.test(a)&&b&&HAN.test(b)&&L[i+1].trim()!=="")out.push(i+1);}
console.log(out.length,out.join(","));'

Why it is worth a row rather than a shrug

The defect is invisible in the source and visible only in the render, which is the inverse
of the usual reading: a reviewer reads this file as source, where the break looks like
ordinary wrapping, while the space exists only for the agent reading the RENDERED text —
and that population is every dispatched dev, once per run. This is the most-read agent
definition in the repo.

Cost, and the one trap in paying it

Cheap but not free: the file sits at 470/470 with headroom 0, so merging a break back
into its paragraph must be re-wrapped canonically and can only shrink or hold the line
count (shrinking lets the ceiling come down with it — always legitimate).

⚠️ The paydown is SELF-CONCEALING under review, and the gate's own docblock says so: a
faithful re-wrap must PRESERVE the rendered space, so it migrates out of the line break and
into a literal ", " in the source, and then looks like the re-wrap introduced a space. It
did not — it only made an existing render visible. The honest fix for prose like
必要不充分: | 实测 is to drop the space entirely (the author never wrote one), which is
what the PR above did for the two breaks inside the passage it re-flowed. Judge each site;
do not batch-convert.

Lineage

The class was found and shut in #12081; the already-literal variant of the same stray space
was recorded in #12265. Neither is open, and neither tracks this file's remaining count —
which is why this is a row rather than a comment on those.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    on Aug 28, 2026
  2. os-litant commented on Aug 28, 2026

    @os-litant
    ContributorAuthor

    Skills-lane self-triage (Director/skills seat, session session_01MnijPVVDakqK2J335JoJtq): graded pm:queue, type Task, domain:skills, priority LOW — real but cosmetic-rendering class: 8 pre-existing #12081-class soft breaks (Han + ASCII punct tail) in .claude/agents/os-dev.md, each rendering as a stray mid-sentence space in the file every dispatched dev reads; the offer-side channel is already shut at the ratchet, so the population cannot grow — this is pure paydown. Scope: re-flow exactly the 8 recorded sites with the ratchet's own wrapLine (content-preservation proved by whitespace-normalize equality, the PR-12890 method), let the line count land where the canonical re-flow puts it and the ratchet ceiling follow it down; the card's self-concealing-paydown note is binding — verify the site list against the tree at dispatch time by re-running the reproduce snippet, never from this card's line numbers. Serial: dispatches only after PR #12890 merges (same file). Queue position: behind ui#5985 · ui#5914 · #12888 — LOW priority yields to all standing queue entries.


    Generated by Claude Code

  3. added
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 28, 2026
  4. added theissue type on Aug 28, 2026
  5. os-litant commented on Aug 28, 2026

    @os-litant
    ContributorAuthor

    Claim: Director/skills seat, session session_01MnijPVVDakqK2J335JoJtq
    Branch: claude/issue-12891-osdev-softbreak-paydown
    Worktree: ../objectstack-12891
    Domain: skills
    File surface: .claude/agents/os-dev.md only — pure paydown re-flow of the 8 recorded #12081-class soft-break sites, wrapLine-canonical, content-preservation by whitespace-normalize equality; site list re-derived from the live tree at dev time (the card's self-concealing-paydown note is binding), ratchet ceiling follows the re-flow down.
    Container & model: opus via the recorded clause-① exit — the path is fable-mandated, and this card is the mechanical-governed-edit class (zero content change, machine-proved preservation); compensation, recorded here as at the previous exit: this seat's collection review runs at its own fable tier. Clause-② limb: no.
    Serial: cleared — PR #12890 merged 2026-08-28T09:32Z (same file released); all higher-priority queue entries are landed or blocked on a different serial (the platform-readings card waits on the SKILL.md holder). Race re-read done this minute: sole comment is this seat's grading.


    Generated by Claude Code

  6. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 28, 2026
  7. self-assigned this
    on Aug 28, 2026
  8. os-litant commented on Aug 28, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 12891,
      "status": "done",
      "premise_still_valid": true,
      "branch": "claude/issue-12891-osdev-softbreak-paydown",
      "pr_number": 12945,
      "pr_url": "https://github.com/objectstack-ai/objectstack/pull/12945",
      "draft": true,
      "sites_before": 8,
      "sites_after": 0,
      "sites_before_lines": [15, 32, 87, 99, 245, 356, 361, 454],
      "line_count_before_after": "470 -> 466",
      "ceiling_movement": "470 -> 466 in CEILINGS['.claude/agents/os-dev.md'], restoring the map's headroom-0 convention. The gate does NOT auto-ratchet on shrink (verdict() passes with positive headroom and only hints above 120), so the recorded ledger entry was updated, matching the same closure's earlier 48 -> 46 lowering of references/decision-analysis.md.",
      "normalize_equality": "proved",
      "normalize_equality_detail": "Whole-file whitespace-normalize byte-equality, 39313 B on both sides, re-confirmed independently against the COMMITTED blobs (base 4d1142753 at 470 lines vs 99addb55f at 466 lines). Proved before the write; the writer refuses to write on any mismatch. Backed by a per-site render-delta proof, because normalize-equality alone would accept a seam that fused two words (stripping whitespace makes 'word word' and 'wordword' equal): for each of the 8 sites the paragraph's rendered text before equals its rendered text after PLUS exactly the one stray space, and nothing else moved. 8/8.",
      "method": "Site list re-derived from the live tree at branch head (never from the card's line numbers) using the gate's own exported hanAsciiPunctTail plus its initialState/advanceState block-state machine; it reproduced the card's 8 sites exactly. Each site's line was joined with the REST OF ITS PARAGRAPH and re-wrapped by the gate's own exported wrapLine; lines ahead of a site are byte-identical. Seams follow the recorded precedent (commit 0acadda3d, which created this rule and paid down 34 of these): nothing is inserted where the defect break was, so the stray space is removed rather than migrated into the source as a literal. A 2-line merge was measured first and DISCARDED: it stranded overflow as orphan fragments and grew the file 470 -> 473.",
      "gates": [
        { "name": "check:pm-skill-ratchet", "verdict_line": "check-skill-line-ratchet: .claude/agents/os-dev.md is 466 lines (ceiling 466; headroom 0).", "exit": 0 },
        { "name": "check:pm-skill-ratchet --self-test", "verdict_line": "check-skill-line-ratchet self-test: 111 cases pass.", "exit": 0 },
        { "name": "check:pm-skill-id-lint", "verdict_line": "check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).", "exit": 0 },
        { "name": "check:skill-frame-sync", "verdict_line": "check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files; binding sentence present in all 4; 42 markdown files scanned.", "exit": 0 },
        { "name": "check:nul-bytes", "verdict_line": "check-nul-bytes: OK (scanned 7177 text file(s); no raw ASCII control bytes).", "exit": 0 },
        { "name": "check:pm-governed-merges", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:pm-governed-prose", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:pm-dispatch-gates", "verdict_line": "exit 0 (convention-triggered: this PR edits a gate script)", "exit": 0 },
        { "name": "bare-root-worklist --self-test", "verdict_line": "exit 0 (convention-triggered: this PR edits a gate script)", "exit": 0 },
        { "name": "check:agent-model-declared", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:agent-test-spelling", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:doc-authoring", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:entry-guard", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:parse-guard", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:watch-hint-literal", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:bash32-floor", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:cli-command-ids", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:pnpm-filter-targets", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check:cross-package-test-inputs", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check-published-list-mirrors", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check-skills-token-ratchet", "verdict_line": "check-skills-token-ratchet: 38 authored bundle file(s) within their ceilings.", "exit": 0 },
        { "name": "check-ci-filter-parity", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check-cross-package-test-inputs", "verdict_line": "exit 0", "exit": 0 },
        { "name": "check-governed-queue-guard", "verdict_line": "NOT MEASURED - 'could not read GITHUB_EVENT_PATH'. It reads the workflow event payload and must not exit 0 when it cannot look; unrunnable outside CI, which runs it.", "exit": 1 }
      ],
      "gates_note": "Union derived mechanically by 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack' (it reads the change set from the merge base itself; 2 paths, 19 matched families + 2 convention-triggered for the gate-script edit). Re-run in full AFTER the final commit; the readings above are from that run at HEAD 99addb55f. Exit codes captured before any pipe. 22 of 23 green, the 23rd not measurable locally.",
      "file_surface": [".claude/agents/os-dev.md", "scripts/pm/check-skill-line-ratchet.mjs"],
      "file_surface_note": "One line beyond the dispatched surface: the CEILINGS entry the shrink obliges, which the dispatch anticipated ('do whatever the gate itself demands'). scripts/pm/ is not itself a governed surface, and the PR is governed regardless via .claude/agents/os-dev.md, so the handling is unchanged.",
      "channel_switch": "Declared. Repo-scoped REST is 403 for this seat (measured this run: 'GitHub access is not enabled for this session', gh absent) - the recorded container-dev-seat shape. The skip-changeset label therefore went through the MCP fallback: read current set -> union -> whole-group write -> comparative read-back. Read set was ['size/s'] (a size labeler had already written); union ['size/s','skip-changeset']; live set after the write equals that union, so nothing was stripped.",
      "mcp_calls": 8,
      "stopped": false,
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  9. os-litant commented on Aug 28, 2026

    @os-litant
    ContributorAuthor

    收件复审 verdict (Director/skills seat, session session_01MnijPVVDakqK2J335JoJtq): ACCEPT — 采纳原文,零改动。⚠️ 本复审即认领时记录的 clause-① 档位出口补偿(机械类治理面编辑 → opus 开发),已以本席 fable 档执行为实质逐段比对。

    PR #12945: all 8 sites re-derived from the live tree (matched the card exactly), re-flowed with the gate's own wrapLine; every seam verified Han-Han (renders spaceless), content preservation proved TWICE — whole-file whitespace-normalize byte-equality (39,313 B both sides, re-confirmed against committed blobs) plus the per-site render-delta proof that closes the fused-words hole bare normalization leaves; the measured-and-discarded 2-line-merge alternative is the right restraint. The one line beyond the dispatched surface (CEILINGS 470 → 466) is the gate's own demanded mechanism, anticipated by the dispatch, with an honest ledger comment; 4 of 8 sites paid for themselves. 22/23 gates green, the 23rd CI-only by design.

    四件套: ② PR stays DRAFT; ③ review pushed to both authorized accounts in this stroke; ④ awaiting 人工直合 或 授权批准钉 current head ⇒ 队列放行.


    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

Labels

domain:skillsDomain lane — seat card indexed by label:pm:seat

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions