docs(design): §09 still specifies 各阶段合同数漏斗 — the app stopped shipping a funnel in #48 and narrowed what it plots in #59 - #70
Merged
Conversation
§09 still specified 各阶段合同数漏斗 — a funnel over every lifecycle stage. Two merged cards moved the app off that in two independent ways, and the design authority never caught up: - #48 / PR #57 replaced the mark with `type: 'horizontal-bar'` ordered by the measure, because a funnel asserts monotonic decline over a book that does not decline (§10: draft 10 · submitted 6 · in_review 12 · in_approval 8 · approved 4 · signing 6 · active 60 — a bowtie). - #59 / PR #62 narrowed the filter to the six in-flight stages, on the criterion the widget's comment states: whether legal still has work to do on the stage. `active` and the four terminal outcomes are all out. The bullet now names the mark and the coverage; a new paragraph carries the reasoning and states that no authored stage order is promised — `options.stageOrder` is read only by console 17.4.0's funnel branch and is dropped silently outside `en` (objectstack-ai/objectstack#17344). Promising an ordering this platform version cannot deliver is the same defect class PR #40 just removed from this section. Documentation only: no app file changes, and no gate reads `DESIGN.md`. 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 11:21
zhuangjianguo
pushed a commit
that referenced
this pull request
Sep 10, 2026
The legal dashboard's header carried a copy of §09's six-brick list. That copy drifted three times in two days — two items rewritten by PR #40 (1127e52), the third by PR #70 (30fd863) — and by the end all three described bricks this file does not implement. Replace the copy with a pointer to §09, which cannot drift. The cycle-time dataset's stage-count paragraph contrasted its counts with "the status funnel on the legal workbench", a funnel that has not existed since PR #57 made that widget a bar chart. Keep the measurement and its reason (signed_at 72 exceeds submitted_at 60; backfilled in-force book, no intake) and drop the claim that a funnel exists to contrast with. Comments only: no metadata, no behaviour, no DESIGN.md change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
zhuangjianguo
pushed a commit
that referenced
this pull request
Sep 10, 2026
Two comments quoted a 09 that has since moved — the mirror of the cards that fixed documents describing code wrongly. legal.dashboard.ts's header carried a copy of 09's six-item brick list, and the copy lost the race three times in two days: two items were rewritten by PR #40 (1127e52) and the third by PR #70 (30fd863), leaving all three describing bricks this file does not implement — the board ships review_ageing titled "In Review Over 30 Days", approval_throughput titled "Approved This Month", and a horizontal-bar. Two of them named metrics 09 now explicitly declines to deliver. The quote is removed rather than updated: updating buys correctness until the next 09 edit and leaves the same trap armed, while a pointer cannot drift. The header now says the list is deliberately absent, so the next reader does not paste it back, and cites commit shas — immutable — instead of prose. cycle-time.dataset.ts contrasted its five coverage counts with "the status funnel on the legal workbench", which has been a horizontal-bar since PR #57. The contrast is inverted rather than deleted: there is no funnel there either, and the same non-monotone book is the reason. The measurement stays — signed_at (72) exceeding submitted_at (60), and the backfill that explains it. Comments only: no metadata key, no widget, no dataset field, no dimension. These files are inside the gates' surface and the gates pass — but comments are invisible to tsc, which is why the drift went unnoticed for two days. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
zhuangjianguo
pushed a commit
that referenced
this pull request
Sep 10, 2026
09 changed direction on 2026-09-09 (1127e52, PR #40; final state 30fd863, PR #70): per-stage durations and the per-type "over SLA" are outside the V1.0 delivery surface, the legal bricks are 30-day review ageing and approval throughput, the executive position carries per-rung routing volume, and the cycle-time dataset carries stage-reached counts with no duration measure. Five comments under src/ still described the 09 that existed before that ruling, reading as "09 asks for X and we cannot deliver it" when 09 now declines X for the very reasons those comments give. The authority ran backwards: the source file was presented as falling short of the design while it is in fact what the design settled on. Each is now written as what the code delivers and why that is right, citing 09 as the authority that agrees. No measurement is deleted — Field.datetime stored as ISO text so AVG() answers an average year, the -0.85 that is the difference of two average years, ADR-0021 leaving the semantic layer no SQL and no expressions, sys_approval_request holding zero rows on a stock demo — because 09 now cites those same measurements as its reasons, and they were taken here. executive.dashboard.ts's header took #71's remedy: the copied 09 brick list is gone and a pointer replaces it, naming the one brick it advertised that this file never built so nobody pastes the list back. Three stale forward-promises went with the framing, all of them things 09 now forbids or the code does not have: - "a persisted review_due_at stamped by the daily job belongs to card 09" — 09 forbids filling the per-type breach from an application-side job, and decision #31 ruled the same way on the notification side (legal-review-sla .flow.ts already said so). - "a daily job stamping clm_contract ... Raised on the PR" for durations — same prohibition. - 'the group title says "Routing Load"' — there is no group title and no such string; the four tiles are titled "Routes: <rung>". Every citation of objectstack#16737 now carries the qualifier: the in-flight platform fix makes the wrong path ERROR rather than adding date arithmetic, so a duration stays uncomputable after it lands. It merely stops rendering a plausible fake number. Comments only: no type, filter, options, dataset field, dimension or widget id, and no line outside comment syntax changed. These three files are inside all four gates' surface and the gates pass — but comments are invisible to tsc, which is exactly why the drift went unnoticed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
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 #63
DESIGN.md§09 still specified the Legal Workbench stage widget as 各阶段合同数漏斗 — a funnel over every lifecycle stage. Two merged cards moved the app off that in two independent ways, and the design authority never caught up. This is a documentation-catches-up card: no app file changes.What §09 said on
9b7538a, verbatimRe-derived on the branch base rather than inherited: §09 spans lines 293–309 on
9b7538a(heading## 09 分析at 293,## 10 种子数据at 310). The target string was present verbatim on line 302, at the end of the 法务工作台 bullet:PR #40 (
296fab8) had already rewritten the rest of this bullet — 超 SLA → 审查超 30 天(固定阈值…), 平均周转 → 审批吞吐(…用平台compareTo)— and appended the 各段时长 ruling paragraph. 漏斗 was the one stale item left in the bullet. This edit sits alongside that rewrite: the 各段时长 paragraph and every other row are byte-identical.The change — two hunks, both inside §09
Hunk 1, line 302 — the bullet now names the mark and the coverage:
Hunk 2, new line 310 — a paragraph carrying the reasoning and, critically, the non-promise about stage order.
stageOrder— which is exactly the defect class PR #40 removed from this section by recording, not by deleting silently.Every claim traced to
src/dashboards/legal.dashboard.tsas mergedtype: 'horizontal-bar'(L347)id: 'stage_funnel'(L344); zh-CN bundle title各阶段合同数(src/translations/zh-CN/app.ts:202); enPipeline by Stagetypeis notfunnel; comment §「Why not a funnel (issue #48) — the mark was making a false claim」 (L278–302); description "not a conversion sequence" (L346)assertSpreadinsrc/data/plan-contracts.ts;DESIGN.md§10 line 320 states the same spreaddraft/submitted/in_review/in_approval/approved/signing入图filter: { status: { $in: ['draft','submitted','in_review','in_approval','approved','signing'] } }(L351)active与rejected/expired/terminated/cancelled四种终态都不入图$inlist (L351); comment L214–233; description "Contracts already in force are not plotted." (L346)active_contract_valueby currency, plusexpiring_90_days" (L271–273); §09's own 管理层 bullet (line 303, unchanged)sortBy: 'contract_count'/sortOrder: 'desc')options: { sortBy: 'contract_count', sortOrder: 'desc' }(L352–355); "it lowers toorder: { contract_count: 'desc' }on the dataset query" (L327–328)optionscarries nostageOrder(L352–355)stageOrdercategoryOrderis consumed inside thechartType === 'funnel'branch and nowhere else" (L308–311)stageOrderstill authored came out Active · Approved · Draft · … i.e. alphabetically" (L311–313)en语言下连漏斗分支也因标签不匹配而丢objectstack-ai/objectstack#17344Gates — all four
0, on8ecfb1cEach redirected to its own file with
$?read on the next statement; no pipe between the command and the exit code.lintreports21 warning(s), 5 suggestion(s)andvalidate27⚠— all pre-existing and none of them reachable from this diff, which changes no metadata (see the disjointness measurement below).⛔ None of the four gates reads
DESIGN.md— measured three ways, not asserted1. Grep the four gate logs. No gate log mentions
DESIGN.md, or any.mdfile at all:2.
tsc --noEmit --listFiles— what typecheck actually opens.3. Ablation — corrupt the file and watch nothing notice. The decisive one. With the fix committed first (so the restore leg points at
HEAD),DESIGN.mdwas overwritten with two lines of garbage, the mutation proven on disk, and all four gates re-run:A file that has been reduced to two lines of non-markdown passes every gate unchanged. The gates verify that the metadata parses; they say nothing whatsoever about this diff. The only checks on this change are the reading table above and human review.
Restore verified by state, not by an exit code —
git hash-object DESIGN.md=4bf1529b73a88b366b8707f9a6357216d55887b8=git rev-parse HEAD:DESIGN.md,git diff HEADempty,git statusclean, corruption marker absent, 303 lines back.4. (bonus) Diff/walk disjointness.
git diff --name-only 9b7538a..HEAD=DESIGN.md, and its intersection with the gates' walk root (objectstack.config.ts+src/**, pertsconfig.jsoninclude) is 0 lines. Every byte the gates read is identical to9b7538a.Edit verified on disk by before/after counts — never by an editor's exit code
各阶段合同数漏斗横向条形图在办sortBystageOrder17344漏斗still matches 1 line — deliberately. That line is the new paragraph, which uses the word only to deny it (不是漏斗 / 漏斗断言逐级单调递减 / 画成漏斗是在断言数据没说的事 / 只有漏斗分支读stageOrder). It is no longer the widget's name anywhere.Both edit anchors were asserted to match exactly once before replacement, so an exact-match edit that silently matched nothing could not have reported success.
Scope
DESIGN.md§09 only. §09 now spans 293–311; the changed lines are 302 and 310–311, both inside it. §01–§04 (lines 24–205) are byte-identical — samesha256before and after (9d1de298628d97616a705d6e4be904768a0c06b14591354e3b5939f8ed8abc67).Acceptance notes — the grep for other descriptions of this widget
Grepped
漏斗andfunnelrepo-wide and各阶段/stage_funnel/Pipeline by StageacrossDESIGN.md.§02 is clean for this widget. Its Insights row (line 80) reads 「阶段时间戳 → dataset → 看板:交付各阶段到达数与审批吞吐,各段时长等平台日期能力(§09)」 — that points at the
contract_cycle_timedataset and theapproval_throughputtile, not at the stage bar, and it says nothing about a funnel or about coverage. PR #40 already corrected that row. No stale pointer here, and §02 is inside the governed range regardless.Both translation bundles are already correct —
stage_funnel.titleisPipeline by Stage/各阶段合同数, and the zh-CN description already says 「六个阶段…按数量从多到少排列,不是转化流程。已生效的合同不在此图内。」 The new §09 wording was aligned to these shipped strings rather than to the card's prose.Two stale occurrences remain, both in app source, both left untouched on purpose. The card and the dispatch both say ⛔ do not touch the app; these are named here rather than silently left, so the seat can decide:
src/dashboards/legal.dashboard.ts:4-5— the file header quotes §09's 法务工作台 list to identify which dashboard it implements, and that quote is stale twice over: it still says平均周转(本月 vs 上月)(PR Record four maintainer rulings in DESIGN.md §03, §06 and §09 #40 changed §09 to 审批吞吐) and各阶段合同数漏斗(this PR). One line, mechanical.src/datasets/cycle-time.dataset.ts:44-45— "The status funnel on the legal workbench is the honest funnel; these are per-stage coverage counts." The status widget has not been a funnel since PR Draw 「Pipeline by Stage」 as a ranked bar, not a funnel #57, so the sentence's contrast no longer holds.Neither is a runtime defect: both are comments, invisible to the gates and to the product. They are the same stale-pointer pattern the card warned about, pointing the other way — code quoting a document instead of a document describing code. Suggest one follow-up card covering both; not filed, so as not to pre-empt the seat's split.
🤖 Generated with Claude Code
https://claude.ai/code/session_01R3n3GGzobdegM4HUzah1iR
Generated by Claude Code