Repository navigation
§06 F14 says an archived contract stays editable 「除 notes 外」, but clm_contract has no notes field — §03 gives it summary - #68
Merged
Conversation
DESIGN.md §06 F14 said an archived contract stays editable 「除 `notes` 外只读」, but §03 gives `clm_contract` a `summary` field and puts `notes` on the child objects only — there is no `notes` on the contract, so the sentence named a field that does not exist. The implementation is not wrong; the sentence is. The F14 freeze in src/objects/contract.hook.ts leaves `summary` open (plus the engine's own audit columns), which is the only reading that leaves an archived record annotatable at all — taking §06 literally would freeze the contract completely. One word, in a section outside the governed range (§01-§04). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
zhuangjianguo
marked this pull request as ready for review
September 10, 2026 10:57
This was referenced Sep 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #44
DESIGN.md§06 F14 said an archived contract stays editable 「除notes外只读」, but §03 givesclm_contractasummaryfield and putsnoteson the child objects only. The contract has nonotes, and never had one. The implementation is not wrong; the sentence is.One word, one line, in a section outside the governed range:
git diff --stat 296fab8..HEAD→DESIGN.md | 2 +- · 1 file changed, 1 insertion(+), 1 deletion(-).Premise re-verified on
296fab8PR #40 merged shortly before this branch was cut and moved
DESIGN.md§02, §03, §06 and §09. Both premises of the card were re-read on the tree this branch cuts from, not inherited from the card:296fab8DESIGN.md:239, inside §06 (headers: §06 at line 222, §07 at line 245). The file spells it 「此后除notes外只读」 —notesin backticks; the card quoted it with the code formatting dropped. Same sentence, same F, untouched by #40.clm_contractasummaryand nonotesclm_contractrow (DESIGN.md:108) carriessummary richtext;notesoccurs zero times in that row. In §03notesappears only onclm_contract_version,clm_signature,clm_obligation,clm_payment_plan.The reading this card actually rests on
That
summaryis the field F14's freeze leaves open is a claim about code, so it is answered by reading the code on this tree — not by a gate run. Rows 1–3 are direct source readings; rows 4–7 read the branch that produces each measured response, confirming the card's measurements still describe296fab8unchanged.296fab8clm_contracthas asummaryfield, nonotessrc/objects/contract.object.ts:366summary: Field.richtext(…).grep -c notes src/objects/contract.object.ts→ 0.summaryopensrc/objects/contract.hook.ts, hookcontract_archive:OPEN_AFTER_ARCHIVE = ['summary', 'id', 'organization_id', 'created_at', 'created_by', 'updated_at', 'updated_by'].summaryis the only caller-authorable name in that list — the other six are the id, the tenant column and the engine's audit columns, which ride along on every write.notesentry would match nothing onclm_contract, leaving no writable field; the hook's own comment records this, andarchived_atisreadonly(contract.object.ts:440) with no outgoing edge from the terminal states.archive_noon anactivecontract → 422 naming the statusgainsArchiveNo && !terminalthrowsrefuse(…, 'INVALID_STATE', 422)with the status interpolated:"…this one is active. Let it expire, terminate it or cancel it first."TERMINAL = ['expired', 'terminated', 'cancelled'].archive_noon aterminatedone → 200,archived_atstampedinput.archived_at = new Date().toISOString(). The stamp is the archive event.summaryon an archived contract → 200summaryis inOPEN_AFTER_ARCHIVE, soattemptedis empty and the hook returns without refusing.title→422 Fields refused: titletitleis absent from the allow-list, so it lands inattempted; the thrown message is"This contract was archived on …; only its summary can still be edited. Fields refused: title.",INVALID_STATE, 422.The hook's existing comment already states the resolution this PR writes into §06: 「
clm_contractcarries nonotesfield — §03's field list gives the contractsummary… sosummary, the contract's one free-text column, is the field that stays open」, and closes with "Reported as a §06/§03 wording mismatch rather than resolved by adding a field: §03 is a governed surface." This PR is that report being closed out on the §06 side.Gates
Four gates, each redirected to a file with
$?read on the next statement — no pipe between the command and the exit code.pnpm validate✓ Validation passed (2275ms)pnpm lint21 warning(s), 5 suggestion(s) (1367ms)pnpm typechecktsc --noEmit, no diagnosticspnpm lint:i18n-gate✓ i18n gate·COVERAGE : 0 missing keys across 2 locale(s)None of these four gates reads
DESIGN.md, so none of them verifies this change. Stated plainly rather than implied:tsconfig.jsonincludeis["objectstack.config.ts", "src/**/*"]—DESIGN.mdis not in the typecheck program, and is not TypeScript.validateandlintwalk the compiled metadata graph fromobjectstack.config.ts; neither opens a Markdown file.grep -il DESIGNacross all four gate logs → no match.They are recorded because
AGENTS.mdrequires them green before any PR opens, and they confirm this branch did not disturb the metadata graph. They are not evidence for the sentence. The evidence for the sentence is the reading table above.The
validateandlintwarnings are pre-existing on296fab8and untouched here — carrier-only field notices and one approval-routing suggestion, none of them onclm_contract.summaryor the archive path.Not owed here
.changeset/convention; release notes are written centrally by the maintainer at release time (AGENTS.md).AGENTS.md's browser rule is scoped to cards that change a surface a human touches; a §06 prose line is not one.AGENTS.mdgovernsDESIGN.md§01–§04,AGENTS.md,CLAUDE.md,LICENSE,CHANGELOG.mdanddocs/design/**. §06 is outside that range, so this merges on the normal path and no## 维护者速读comment is owed. §01–§04 were not touched: the whole diff is line 239.Acceptance notes
src/objects/contract.hook.tsquotes the pre-fix §06 sentence verbatim in a comment (「"此后除 notes 外只读" (§06 F14)」) as the premise for its allow-list. After this merges that quote reads as history rather than as the current text — the reasoning it records is exactly what this PR codifies, so it is stale phrasing, not a defect: no runtime behaviour, no gate, no contract depends on it. Deliberately left alone, since the card is one word in §06 and touchingsrc/would widen the diff into the gated surface for a comment. No successor is queued for it — the twoDESIGN.mdcards behind this one (docs: the position census disagrees with itself in three places — README says seven over a table of six, DESIGN.md §11 says both 7 and 8 #58 on §11,DESIGN.md§09 still specifies 各阶段合同数**漏斗** — the app stopped shipping a funnel in #48 and narrowed what it plots in #59 #63 on §09) do not touchcontract.hook.ts.DESIGN.mdcards were not folded in, and no other §06 sentence was touched.🤖 Generated with Claude Code
https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
Generated by Claude Code