Skip to content

§06 F14 says an archived contract stays editable 「除 notes 外」, but clm_contract has no notes field — §03 gives it summary - #68

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-44-design-summary-not-notes
Sep 10, 2026
Merged

zhuangjianguo merged 1 commit into
mainfrom
claude/issue-44-design-summary-not-notes

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes #44

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. The contract has no notes, and never had one. The implementation is not wrong; the sentence is.

One word, one line, in a section outside the governed range:

-| F14 | `contract_archive` | hook beforeUpdate | 终态合同由档案岗填 `archive_no` 后置 `archived_at`,此后除 `notes` 外只读 |
+| F14 | `contract_archive` | hook beforeUpdate | 终态合同由档案岗填 `archive_no` 后置 `archived_at`,此后除 `summary` 外只读 |

git diff --stat 296fab8..HEAD → DESIGN.md | 2 +- · 1 file changed, 1 insertion(+), 1 deletion(-).

Premise re-verified on 296fab8

PR #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:

Card's claim Reading on 296fab8 Holds
§06 F14 says 「此后除 notes 外只读」 Present at DESIGN.md:239, inside §06 (headers: §06 at line 222, §07 at line 245). The file spells it 「此后除 notes 外只读」 — notes in backticks; the card quoted it with the code formatting dropped. Same sentence, same F, untouched by #40. yes
§03 gives clm_contract a summary and no notes The clm_contract row (DESIGN.md:108) carries summary richtext; notes occurs zero times in that row. In §03 notes appears only on clm_contract_version, clm_signature, clm_obligation, clm_payment_plan. yes

The reading this card actually rests on

That summary is 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 describe 296fab8 unchanged.

Claim Reading on 296fab8
clm_contract has a summary field, no notes src/objects/contract.object.ts:366 summary: Field.richtext(…). grep -c notes src/objects/contract.object.ts → 0.
The F14 freeze keeps summary open src/objects/contract.hook.ts, hook contract_archive: OPEN_AFTER_ARCHIVE = ['summary', 'id', 'organization_id', 'created_at', 'created_by', 'updated_at', 'updated_by']. summary is 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.
Taking §06 literally would freeze the contract completely The freeze allow-list is keyed by field name. A notes entry would match nothing on clm_contract, leaving no writable field; the hook's own comment records this, and archived_at is readonly (contract.object.ts:440) with no outgoing edge from the terminal states.
archive_no on an active contract → 422 naming the status gainsArchiveNo && !terminal throws refuse(…, '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_no on a terminated one → 200, archived_at stamped Same branch, terminal side: input.archived_at = new Date().toISOString(). The stamp is the archive event.
Editing summary on an archived contract → 200 summary is in OPEN_AFTER_ARCHIVE, so attempted is empty and the hook returns without refusing.
Editing title → 422 Fields refused: title title is absent from the allow-list, so it lands in attempted; 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_contract carries no notes field — §03's field list gives the contract summary … so summary, 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.

Gate Exit Verdict line it printed
pnpm validate 0 ✓ Validation passed (2275ms)
pnpm lint 0 21 warning(s), 5 suggestion(s) (1367ms)
pnpm typecheck 0 tsc --noEmit, no diagnostics
pnpm lint:i18n-gate 0 ✓ 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.json include is ["objectstack.config.ts", "src/**/*"] — DESIGN.md is not in the typecheck program, and is not TypeScript.
  • validate and lint walk the compiled metadata graph from objectstack.config.ts; neither opens a Markdown file.
  • Mechanically: grep -il DESIGN across all four gate logs → no match.

They are recorded because AGENTS.md requires 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 validate and lint warnings are pre-existing on 296fab8 and untouched here — carrier-only field notices and one approval-routing suggestion, none of them on clm_contract.summary or the archive path.

Not owed here

  • No changeset. This repo has no changeset gate and no .changeset/ convention; release notes are written centrally by the maintainer at release time (AGENTS.md).
  • No browser run. The diff changes no runnable surface — no object, view, page, app, flow or action. AGENTS.md's browser rule is scoped to cards that change a surface a human touches; a §06 prose line is not one.
  • Not a governed-surface PR. AGENTS.md governs DESIGN.md §01–§04, AGENTS.md, CLAUDE.md, LICENSE, CHANGELOG.md and docs/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


🤖 Generated with Claude Code

https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR


Generated by Claude Code

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

§06 F14 says an archived contract stays editable 「除 notes 外」, but clm_contract has no notes field — §03 gives it summary

2 participants