Skip to content

docs(requirements): freezing protects a statement that was true when written (#1933) - #1946

Merged
os-elon-musk merged 1 commit into
mainfrom
claude/issue-1933-requirements-freeze-policy
Sep 16, 2026
Merged

os-elon-musk merged 1 commit into
mainfrom
claude/issue-1933-requirements-freeze-policy

Conversation

@os-elon-musk

@os-elon-musk os-elon-musk commented Sep 16, 2026 •

Copy link
Copy Markdown
Collaborator

Part of #1933 — the policy half. The implementation half landed in PR #1942; what this card
still owed was the written-down criterion, so the question is not argued card by card again.

⚠️ This body carries no issue-closing keyword, deliberately. #1933 also covers the second
document class (docs/architecture/**), which the PM's own comments keep with the maintainer;
the merge queue would otherwise take the card out of the inbox that half is waiting in.

The ruling this writes down

The maintainer's ruling of 2026-09-16, as adopted rather than as typed. The PM put this
wording to the maintainer, who adopted it with 「其他同意」 — "agreed to the rest". It is quoted
exactly and kept untranslated, because the adopted words are the ruling:

写时为真的陈述冻结;写下时就已失效的路径按错误改正。这条写进 docs/requirements/README,以后不再逐卡吵。

What landed

One new section in docs/requirements/README.md — What freezing protects (2026-09-16
maintainer ruling)
— placed directly under the File layout bullet that makes records
append-only, which is the bullet it qualifies, and above How AI agents consume this.

It is written as a criterion, not a conclusion, so a reader can decide a record nobody has
argued about yet. The criterion is two timestamps:

The record's commit, against the change it cites Verdict
Before the structure it names moved, was renamed, or was deleted Freeze — true when written, and editing it rewrites the history the record exists to hold
After that change Correct it — it named nothing the day it was typed, so it is a typo, not a record

Around that, four things the criterion needs to be usable:

  1. How to measure it. Find the authoring commit (⛔ not the record's Raised: date, which is
    the customer's and can be weeks earlier), then ask whether the cited path was in that
    commit's own tree
    . A lookup in one commit's tree needs no ancestry walk and stays correct on
    the shallow checkout CI hands you. The shallow trap is named beside it: --diff-filter=A there
    reports the graft root as the adding commit and reads exactly like a real answer.
  2. What "correct it" means in practice — repoint per path, read each successor off the tree
    instead of prefixing mechanically, keep the edit to the stale path, and where one file was
    split in two with no same-named successor, name every successor the sentence depends on.
  3. The why, hung on this file's own opening, as the card required and not a second story:
    the README already defines these records as "the human-or-customer input an AI agent reads
    before authoring metadata"
    . A path that resolved to nothing on the day it was written has no
    fact underneath it, so freezing it protects nothing and costs something real — the next agent
    reads the record as the spec it starts from and is sent to a directory that does not exist.
    The quotation was read out of the file with sed -n '6,7p' and joined across its line wrap,
    ⛔ not written from memory; lines 6–7 themselves are untouched.
  4. The two worked examples, which come out opposite ways — that is what makes the criterion
    testable rather than decorative.

The two examples, measured

The ADR-0130 package move is 36b27dd, 2026-09-14T14:07:19Z.

Record Its commit Against the move Tree lookup at its own commit Verdict
REQ-0001 3b72afa, 2026-08-27T08:47:48Z (its latest) 18 days before the routing-flow directory it names is PRESENT frozen, unchanged
REQ-0002 9f13c77, 2026-09-14T14:36:11Z 29 minutes after all three paths it cited are ABSENT, all four successors already PRESENT corrected in PR #1942

Both ancestry legs are positive, so no control leg for a negative is owed:
git merge-base --is-ancestor 3b72afa 36b27dd → exit 0 and
git merge-base --is-ancestor 36b27dd 9f13c77 → exit 0, in a checkout that reports
--is-shallow-repository = true. The tree lookups are the stronger legs and are immune to the
shallow graft; the ABSENT/PRESENT pair above runs the same checker to both outcomes, so it is a
measurement and not a vacuously green loop.

Verification

pnpm verify — the package.json chain run whole, not narrowed
(validate && typecheck && lint && lint:i18n-gate && hygiene && hygiene:tokens && build && test),
through the shared lock. The exit code was written to a file before any pipe touched the
output
, then read back:

os-verify-lock: VERDICT command-exit 0 · held the lock 159s (2m39s) · waited 0s
  ✓ Validation passed (1559ms)
  ✓ i18n lint gate: 0 `i18n/missing-*` issues
  ✓ source hygiene clean
  ✓ source token ratchet clean
  ✓ Build complete (1415ms)
  Test Files  170 passed (170)
       Tests  3646 passed | 1 skipped (3647)

Those seconds are shared-box seconds — several agents run on this container — not idle-box
figures. Run on 0dab9bd, whose tree this head still carries byte-for-byte: the head was
later amended to 5fabd4a for the provenance correction noted below, which touches only the
attribution sentences and leaves every measured byte of the section unchanged.

Two checks beyond the chain, because this file is prose the gates barely read:

  • Dead-path sweep over the edited file. The whole README now yields zero hits for the
    src/DIR form that test/docs-src-tree-paths.test.ts extracts — the new section states the
    post-move shape as the brace placeholder src/{package}/{type}/ and never spells a removed
    directory as a literal. That matters here specifically: this file is not in TREE_DOCS
    today, and this very ruling is what unblocks deriving the other half of that roster, so the
    section must not be the thing that goes red when it does.
  • Control-byte self-scan with grep -naP over both edited files and over this body: no hits.

Changeset — empty frontmatter, and why

.changeset/requirements-freeze-is-about-true-when-written.md ships with deliberately empty
frontmatter
: the sanctioned "this PR releases nothing" declaration that
.github/workflows/changeset-check.yml documents, on par with the skip-changeset label, and the
same form PR #1942 and PR #1944 used for this directory.

The level is judged, not defaulted. Nothing under src/ or content/docs/ moves, so the built
artifact and the published documentation site are byte-identical to main; the diff is one
maintainer-documentation file plus the changeset. A patch bump would publish a HotCRM release
whose notes say nothing a HotCRM installer can act on. The declaration still satisfies both steps
of the gate — it counts as an added changeset, and changeset status parses it — so the label is
not needed and was not spent.

Provenance correction (post-review)

The first revision of this PR labelled the quoted ruling "verbatim and kept untranslated".
The maintainer did not type those words: the PM drafted them and the maintainer adopted them
with 「其他同意」 — "agreed to the rest". Content is unchanged to the byte; only the attribution
sentences were rewritten, in all four places that carried the claim — this body, the section in
docs/requirements/README.md, the changeset, and the commit message (amended in place under
AGENTS.md §3 rather than stacked as a second commit; all five criteria checked, ⑤ pinned the
lease to 0dab9bd). This file is a long-lived policy document that will be cited as "what the
maintainer said", and this very card was opened by a misquotation, so adopted-versus-typed is
worth the extra sentence.

Boundaries held

Acceptance notes


Generated by Claude Code

@vercel

vercel Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 16, 2026 8:03am UTC

Request Review

…written

The maintainer ruled the freeze question on 2026-09-16. The wording below is that
ruling as adopted rather than as typed — the PM put it to the maintainer, who adopted
it with 「其他同意」 ("agreed to the rest") — so it is quoted exactly and kept
untranslated, because the adopted words are the ruling.

> 写时为真的陈述冻结;写下时就已失效的路径按错误改正。这条写进 `docs/requirements/README`,以后不再逐卡吵。

`docs/requirements/README.md` gains one section that writes it down as a criterion
rather than a conclusion, so the next reader can decide a record nobody has argued
about yet. The criterion is two timestamps: the commit that wrote the sentence,
against the commit that moved, renamed or deleted the structure it cites. Earlier
means the sentence was true when written and is frozen; later means it named nothing
the day it was typed, which is a typo to correct.

The measurement is given in the cheap, shallow-safe form — a lookup in the authoring
commit's own tree rather than an ancestry walk — with the shallow-checkout trap that
makes `--diff-filter=A` read like a real answer called out beside it.

The "why" hangs on this file's own opening, which already defines these records as
"the human-or-customer input an AI agent reads before authoring metadata": a path
that resolved to nothing the day it was written has no fact underneath it, so
freezing it protects nothing and routes the next agent into a directory that does
not exist.

Both worked examples are already in this directory and come out opposite ways, which
is what makes the criterion testable rather than decorative: REQ-0001 is frozen (its
commits predate the ADR-0130 move, and the directory it names is in the tree at its
own commit), REQ-0002 was corrected in PR #1942 (its commit lands 29 minutes after
that move, and none of the three paths it cited are in the tree at that commit).

No requirement record changes, the template is untouched, and the section states that
it does not decide the document class that describes a superseded tree on purpose.

Claude-Session: https://claude.ai/code/session_01T3YsvpK1PvYf9n1YUhYP6W

Co-authored-by: Claude <noreply@anthropic.com>
@os-elon-musk
os-elon-musk force-pushed the claude/issue-1933-requirements-freeze-policy branch from 0dab9bd to 5fabd4a Compare September 16, 2026 08:03
@os-elon-musk
os-elon-musk marked this pull request as ready for review September 16, 2026 08:09
@os-elon-musk
os-elon-musk added this pull request to the merge queue Sep 16, 2026
Merged via the queue into main with commit fc00afe Sep 16, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants