pomaster 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +393 -396
- package/TRADEMARKS.md +2 -2
- package/catalog/archetypes/archetype.api.error.json +55 -0
- package/catalog/archetypes/archetype.api.pagination.json +68 -0
- package/catalog/archetypes/archetype.api.resource.json +45 -0
- package/catalog/archetypes/archetype.backend.approval_workflow.json +63 -0
- package/catalog/archetypes/archetype.backend.audit.json +44 -0
- package/catalog/archetypes/archetype.backend.crud_resource.json +56 -0
- package/catalog/archetypes/archetype.backend.export.json +40 -0
- package/catalog/archetypes/archetype.backend.external_integration.json +89 -0
- package/catalog/archetypes/archetype.backend.idempotent_command.json +65 -0
- package/catalog/archetypes/archetype.backend.import.json +47 -0
- package/catalog/archetypes/archetype.backend.master_data.json +45 -0
- package/catalog/archetypes/archetype.backend.outbox_event.json +80 -0
- package/catalog/archetypes/archetype.backend.query_resource.json +40 -0
- package/catalog/archetypes/archetype.backend.scheduled_job.json +69 -0
- package/catalog/archetypes/archetype.backend.transactional_write.json +79 -0
- package/catalog/archetypes/archetype.component.button.json +53 -0
- package/catalog/archetypes/archetype.component.data_grid.json +78 -0
- package/catalog/archetypes/archetype.component.dialog.json +52 -0
- package/catalog/archetypes/archetype.component.search_input.json +34 -0
- package/catalog/archetypes/archetype.component.search_select.json +77 -0
- package/catalog/archetypes/archetype.data.hierarchy.json +71 -0
- package/catalog/archetypes/archetype.data.ledger.json +40 -0
- package/catalog/archetypes/archetype.data.master_data.json +43 -0
- package/catalog/archetypes/archetype.data.transaction.json +42 -0
- package/catalog/archetypes/archetype.data.versioned.json +43 -0
- package/catalog/archetypes/archetype.frontend.error_taxonomy.json +99 -0
- package/catalog/archetypes/archetype.frontend.feature_oriented.json +59 -0
- package/catalog/archetypes/archetype.frontend.modular.json +37 -0
- package/catalog/archetypes/archetype.frontend.spa_layered.json +48 -0
- package/catalog/archetypes/archetype.page.analysis.json +39 -0
- package/catalog/archetypes/archetype.page.master_data.json +63 -0
- package/catalog/archetypes/archetype.runtime.environment_parity.json +178 -0
- package/catalog/archetypes/archetype.runtime.observability_binding.json +93 -0
- package/catalog/archetypes/archetype.state.async_command.json +63 -0
- package/catalog/archetypes/archetype.state.background_refresh.json +45 -0
- package/catalog/archetypes/archetype.state.form_edit.json +45 -0
- package/catalog/archetypes/archetype.state.optimistic_mutation.json +48 -0
- package/catalog/archetypes/archetype.state.selection.json +35 -0
- package/catalog/archetypes/archetype.state.server_query.json +60 -0
- package/catalog/archetypes/archetype.state.url_filter.json +47 -0
- package/catalog/archetypes/archetype.state.wizard.json +46 -0
- package/catalog/catalog-lock.draft.json +349 -5
- package/catalog/gates/gate.new-entity.checks.json +106 -0
- package/catalog/knowledge/knowledge.web.browser.mcp_eyes.json +99 -0
- package/catalog/sensors/sensor.browser.deterministic.json +17 -6
- package/catalog/sensors/sensor.browser.interactive.json +16 -6
- package/catalog/tools/materialize_v06_relock.py +218 -0
- package/catalog/tools/seed_v06_archetypes.py +283 -0
- package/catalog/tools/seed_v06_batch2_materials.py +504 -0
- package/catalog/tools/seed_v06_batch3_materials.py +756 -0
- package/catalog/tools/seed_v06_batch4_materials.py +353 -0
- package/dist/bin.js +2920 -331
- package/package.json +1 -1
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""P-v06 批次 2:Frontend 模型 archetype 物料落盘(12 份)。
|
|
3
|
+
|
|
4
|
+
语义全部锚定联网核实报告(.trellis/tasks/09-02-vnext-prd-v06-governed-substrate/
|
|
5
|
+
research/frontend-state-references.md,2026-09-03 官网/规范实抓;FORM_EDIT 校验
|
|
6
|
+
状态四值沿批次 1 external-design-references.md 2026-09-02 AntD Form 实抓):
|
|
7
|
+
- STATE_ARCHETYPE 八态族(v0.6.1 §16 逐字八值):词形/默认档/链序均以 TanStack
|
|
8
|
+
Query v5(5.102.8)/nuqs 2.10.1/XState v5(5.32.6)现行文档实抓为准;
|
|
9
|
+
§17 State Ownership 判定表对应行逐条落进各态 when_to_use/when_not_to_use。
|
|
10
|
+
- FRONTEND_ARCHETYPE 三型(§18 逐字):SPA_LAYERED×MODULAR incompatible 双向登记
|
|
11
|
+
(incompatible 槽首个真实用例);FEATURE_ORIENTED 承载差异表 #4 的 FSD 现行
|
|
12
|
+
6 有效层(Processes deprecated)/无独立 API 层差异声明。
|
|
13
|
+
- FRONTEND_ARCHETYPE.ERROR_TAXONOMY(§21 逐字九分型闭包):每型绑定四列语义位;
|
|
14
|
+
待裁定两项(CANCELED 第十分型/429 归属,差异表 #8)在 x-research-anchors.note
|
|
15
|
+
在场,本物料保持九分型不扩。
|
|
16
|
+
- ASYNC_COMMAND 头号注记(差异表 #7):PRD「Illegal Transition 必须可表达」在
|
|
17
|
+
XState v5 无对应词形(未匹配事件=静默忽略+state.can() 显式守卫)——物料落
|
|
18
|
+
PRD 语义意图(非法组合经 transition contract 显式声明)+实现绑定注记,差异待
|
|
19
|
+
Owner 裁定。
|
|
20
|
+
词形纪律:STATE_*/FRONTEND_* 为 catalog 词形空间(批次 2 PRD:不走 governed
|
|
21
|
+
前缀 PR);id 至少两段 SCREAMING_SNAKE(loadCatalogArchetypes 同一闸)。
|
|
22
|
+
token 纪律:物料 core 词面(title/id/summary/semantic 三槽)避开既有 repo 级
|
|
23
|
+
resolver 断言的 need token(master/data/主数据/按钮/button/资源/create/update/
|
|
24
|
+
delete/select/combobox 等)——分母扩容不改变既有判卷(ADR:批次 2 物料半场
|
|
25
|
+
不回退既有集成断言,只同步分母钉版)。
|
|
26
|
+
幂等:同输入重跑 byte-stable。
|
|
27
|
+
"""
|
|
28
|
+
import json
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
34
|
+
except Exception:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # .../catalog
|
|
38
|
+
OUT = os.path.join(ROOT, "archetypes")
|
|
39
|
+
FETCH = "2026-09-03"
|
|
40
|
+
# FORM_EDIT 校验状态四值的 AntD 实抓出自批次 1 报告(external-design-references.md,
|
|
41
|
+
# 2026-09-02 官网实抓)——日期如实记当日,不冒充本批次实抓。
|
|
42
|
+
FETCH_ANTD_FORM = "2026-09-02"
|
|
43
|
+
|
|
44
|
+
RESEARCH_NOTE_PREFIX = ".trellis/tasks/09-02-vnext-prd-v06-governed-substrate/research/frontend-state-references.md"
|
|
45
|
+
PRD_DOC_REF = "doc/POMaster-vNext-PRD-v0.6.1-Engineering-Substrate-Archetype-Catalog.md"
|
|
46
|
+
|
|
47
|
+
materials = {}
|
|
48
|
+
|
|
49
|
+
# ============================================================
|
|
50
|
+
# STATE_ARCHETYPE 八态族(v0.6.1 §16 逐字八值;layer=PATTERN)
|
|
51
|
+
# ============================================================
|
|
52
|
+
|
|
53
|
+
materials["archetype.state.server_query.json"] = {
|
|
54
|
+
"id": "STATE_ARCHETYPE.SERVER_QUERY",
|
|
55
|
+
"kind": "archetype",
|
|
56
|
+
"layer": "PATTERN",
|
|
57
|
+
"title_zh": "服务端查询状态",
|
|
58
|
+
"summary_zh": "远端资源的异步取数状态原型(TanStack Query v5 词形锚定):数据轴 status 与网络轴 fetchStatus 双轴分离,isPending/isFetching/isLoading 三词形语义各司其职,缓存与后台刷新默认档开箱即用。",
|
|
59
|
+
"semantic": {
|
|
60
|
+
"responsibility": "持有远端取数的缓存、去重与刷新生命周期(stale-while-revalidate),把「有没有数据」与「请求是否进行中」表达为两个正交词轴",
|
|
61
|
+
"when_to_use": "状态的所有权在远端:数据持久化在服务端、经异步 API 获取、可能被他人改动而过期(v0.6.1 §17 判定行「远端资源 → SERVER_QUERY」)——列表/详情/报表取数面默认归位",
|
|
62
|
+
"when_not_to_use": "可分享/可收藏筛选(STATE_ARCHETYPE.URL_FILTER);未保存表单草稿(STATE_ARCHETYPE.FORM_EDIT);纯本地交互态(STATE_ARCHETYPE.SELECTION)",
|
|
63
|
+
},
|
|
64
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
65
|
+
"defaults": {
|
|
66
|
+
"word_form_distinction": {
|
|
67
|
+
"isPending": "数据轴 status==='pending'——尚无任何数据(不等于请求进行中)",
|
|
68
|
+
"isFetching": "网络轴 fetchStatus==='fetching'——queryFn 正在抓取(含后台 refetch,任何 status 下可为 true)",
|
|
69
|
+
"isLoading": "isPending && isFetching——仅「无数据且在抓取」的首次加载词形(v4 isInitialLoading 改名,v5 现行口径)",
|
|
70
|
+
},
|
|
71
|
+
"status_axis": ["pending", "error", "success"],
|
|
72
|
+
"fetch_status_axis": ["fetching", "paused", "idle"],
|
|
73
|
+
"staleTime": 0,
|
|
74
|
+
"gcTime": "5min",
|
|
75
|
+
"retry": 3,
|
|
76
|
+
"structural_sharing": True,
|
|
77
|
+
},
|
|
78
|
+
"forbidden": [
|
|
79
|
+
"单一扁平 loading 布尔同时表达数据有无与请求进行中(v5 拆分双轴)",
|
|
80
|
+
"v4 旧词形:status:'loading' / cacheTime / isInitialLoading",
|
|
81
|
+
"把 isPending 当「请求中」用(应表达为尚无数据)",
|
|
82
|
+
],
|
|
83
|
+
"x-research-anchors": {
|
|
84
|
+
"note": "TanStack Query v5(npm 5.102.8)双轴模型与 Important Defaults(staleTime 0/gcTime 5min/retry 3/structural sharing)为官网 .md 文档实抓;isPending≠isFetching≠isLoading 三词形区分是 v4→v5 breaking 官方口径(2026-09-03 实抓)",
|
|
85
|
+
"sources": [
|
|
86
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/queries.md", "fetched": FETCH},
|
|
87
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults.md", "fetched": FETCH},
|
|
88
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/migrating-to-v5.md", "fetched": FETCH},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
materials["archetype.state.url_filter.json"] = {
|
|
94
|
+
"id": "STATE_ARCHETYPE.URL_FILTER",
|
|
95
|
+
"kind": "archetype",
|
|
96
|
+
"layer": "PATTERN",
|
|
97
|
+
"title_zh": "URL 筛选状态",
|
|
98
|
+
"summary_zh": "以 URL 查询串为事实源的筛选状态原型(nuqs 2.10.1:「the URL is the source of truth」):筛选/分页/排序/tab 定位写入 URL 后天然可分享、可收藏、刷新保留、回退保留。",
|
|
99
|
+
"semantic": {
|
|
100
|
+
"responsibility": "把「可分享/可收藏/刷新保留/回退保留」四触发条件的筛选状态所有权交给 URL,序列化规则单点",
|
|
101
|
+
"when_to_use": "状态需要通过 URL 分享、收藏、刷新后保留或浏览器回退保留时(v0.6.1 §17 判定行「可分享/可收藏的筛选条件 → URL」)——列表筛选、分页、排序、tab 定位是典型",
|
|
102
|
+
"when_not_to_use": "大对象/不可序列化状态;临时展开/选中(STATE_ARCHETYPE.SELECTION);高维筛选全量入参会参数爆炸(只放分享者视角关键参数)",
|
|
103
|
+
},
|
|
104
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
105
|
+
"defaults": {
|
|
106
|
+
"source_of_truth": "URL is the source of truth(nuqs 自我定位)",
|
|
107
|
+
"serialization": "search_params_string",
|
|
108
|
+
"read_only_view_client": True,
|
|
109
|
+
"replace_history_for_typed_input": True,
|
|
110
|
+
"push_history_for_discrete_changes": True,
|
|
111
|
+
"dual_surface_note": "Next.js App Router 双端形态:Client 侧 useSearchParams 只读同步(prerendered 路由须包 Suspense 边界);Server 侧 Page searchParams prop 为 Promise 异步形态(v15 起,同步访问已标记将废弃)",
|
|
112
|
+
},
|
|
113
|
+
"forbidden": [
|
|
114
|
+
"Server Component 直接调 useSearchParams(Next.js 明确不支持)",
|
|
115
|
+
"prerendered 路由无 Suspense 边界使用 client searchParams hook",
|
|
116
|
+
"绕过序列化规则自造查询串格式(有 nuqs/框架 adapter 时应引用)",
|
|
117
|
+
],
|
|
118
|
+
"x-research-anchors": {
|
|
119
|
+
"note": "nuqs npm latest 2.10.1 与 GitHub README「the URL is the source of truth」实抓;Next.js 16.3.4 文档 useSearchParams 只读 client 形态与 Page searchParams Promise 双端形态实抓(2026-09-03)",
|
|
120
|
+
"sources": [
|
|
121
|
+
{"url": "https://registry.npmjs.org/nuqs", "fetched": FETCH},
|
|
122
|
+
{"url": "https://nextjs.org/docs/app/api-reference/functions/use-search-params.md", "fetched": FETCH},
|
|
123
|
+
{"url": "https://nextjs.org/docs/app/api-reference/file-conventions/page.md", "fetched": FETCH},
|
|
124
|
+
],
|
|
125
|
+
},
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
materials["archetype.state.form_edit.json"] = {
|
|
129
|
+
"id": "STATE_ARCHETYPE.FORM_EDIT",
|
|
130
|
+
"kind": "archetype",
|
|
131
|
+
"layer": "PATTERN",
|
|
132
|
+
"title_zh": "表单编辑草稿状态",
|
|
133
|
+
"summary_zh": "未保存表单草稿的本地编辑状态原型:字段值、校验状态与脏标记归表单容器持有,不进全局 Store 也不写 URL;校验状态词形按 AntD Form validateStatus 四值锚定。",
|
|
134
|
+
"semantic": {
|
|
135
|
+
"responsibility": "持有未提交草稿的字段值/校验结果/脏标记,提交成功后交出所有权",
|
|
136
|
+
"when_to_use": "未保存表单草稿(v0.6.1 §17 判定行「未保存表单草稿 → FORM」)——编辑抽屉/对话框内草稿、多字段录入面",
|
|
137
|
+
"when_not_to_use": "已提交数据的远端缓存(STATE_ARCHETYPE.SERVER_QUERY);可分享筛选(STATE_ARCHETYPE.URL_FILTER)",
|
|
138
|
+
},
|
|
139
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
140
|
+
"defaults": {
|
|
141
|
+
"ownership": "form_container_local",
|
|
142
|
+
"validation_status_words": ["success", "warning", "error", "validating"],
|
|
143
|
+
"validation_status_source": "AntD Form validateStatus 官方四值(external-design-references.md 2026-09-02 正文明抓)",
|
|
144
|
+
"dirty_tracking": "pristine/dirty 二态起点",
|
|
145
|
+
},
|
|
146
|
+
"forbidden": [
|
|
147
|
+
"草稿直写全局 Store(v0.6.1 §17「禁止默认全部放全局 Store」的表单形态)",
|
|
148
|
+
"校验状态自造第五词形(success/warning/error/validating 四值闭包外)",
|
|
149
|
+
],
|
|
150
|
+
"x-research-anchors": {
|
|
151
|
+
"note": "校验状态四值 success/warning/error/validating 为 AntD Form API 正文明抓(external-design-references.md 对应锚,2026-09-02);§17 判定行与禁全局 Store 语义为 PRD 事实源(2026-09-03 对照 frontend-state-references.md 差异表 #3 无冲突确认)",
|
|
152
|
+
"sources": [
|
|
153
|
+
{"url": "https://ant.design/components/form", "fetched": FETCH_ANTD_FORM},
|
|
154
|
+
{"url": PRD_DOC_REF + " §17", "fetched": FETCH},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
materials["archetype.state.selection.json"] = {
|
|
160
|
+
"id": "STATE_ARCHETYPE.SELECTION",
|
|
161
|
+
"kind": "archetype",
|
|
162
|
+
"layer": "PATTERN",
|
|
163
|
+
"title_zh": "临时选中状态",
|
|
164
|
+
"summary_zh": "临时展开/选中类本地交互状态原型:生命周期限于当前视图实例,刷新即失、不入 URL、不进全局 Store——最便宜的所有权归最近持有者。",
|
|
165
|
+
"semantic": {
|
|
166
|
+
"responsibility": "持有视图实例私有的瞬时交互态(行选中/展开/焦点/tab 内高亮)",
|
|
167
|
+
"when_to_use": "临时展开/选中(v0.6.1 §17 判定行「临时展开/选中 → LOCAL_UI」)——组件本地 useState 即默认落点",
|
|
168
|
+
"when_not_to_use": "刷新后需保留的状态(升 STATE_ARCHETYPE.URL_FILTER 或 SERVER_QUERY);跨页面会话(DOMAIN/SESSION 所有权,§17 判定行「跨页面业务 Session」);「禁止默认全部放全局 Store」对本态最严格",
|
|
169
|
+
},
|
|
170
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
171
|
+
"defaults": {"ownership": "component_local", "persist_scope": "none", "restore_on_refresh": False},
|
|
172
|
+
"forbidden": [
|
|
173
|
+
"把临时选中提升进全局 Store(§17 禁默认全部放全局 Store)",
|
|
174
|
+
"把可分享筛选降格为本地位(应升 STATE_ARCHETYPE.URL_FILTER)",
|
|
175
|
+
],
|
|
176
|
+
"x-research-anchors": {
|
|
177
|
+
"note": "所有权判定锚 PRD §17 State Ownership Resolver 判定表(2026-09-03 对照 frontend-state-references.md 差异表 #2/#3 无冲突确认)",
|
|
178
|
+
"sources": [{"url": PRD_DOC_REF + " §17", "fetched": FETCH}],
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
materials["archetype.state.async_command.json"] = {
|
|
183
|
+
"id": "STATE_ARCHETYPE.ASYNC_COMMAND",
|
|
184
|
+
"kind": "archetype",
|
|
185
|
+
"layer": "PATTERN",
|
|
186
|
+
"title_zh": "异步命令状态机",
|
|
187
|
+
"summary_zh": "以 XState v5 六概念(state/event/transition/guard/actor/input/output)承载的异步命令原型:命令参数经 input 进入,状态经 guarded transition 确定性转移,final state 产出 output;非法组合经 transition contract 显式声明(实现侧绑定 state.can() 守卫位)。",
|
|
188
|
+
"semantic": {
|
|
189
|
+
"responsibility": "把一次异步命令(提交/保存/执行)建模为显式状态机:idle/running/done|error 转移全部声明在案,guard 纯同步布尔",
|
|
190
|
+
"when_to_use": "命令的合法状态转移需要显式契约时(非法组合必须可表达为「未声明的 transition 不存在」);多步骤异步编排(invoke/spawn actor)",
|
|
191
|
+
"when_not_to_use": "远端取数缓存语义(STATE_ARCHETYPE.SERVER_QUERY);无需显式转移契约的局部加载布尔",
|
|
192
|
+
},
|
|
193
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
194
|
+
"defaults": {
|
|
195
|
+
"vocabulary": ["state", "event", "transition", "guard", "actor", "input", "output"],
|
|
196
|
+
"guard_nature": "pure_synchronous_boolean",
|
|
197
|
+
"guard_style": "serialized_named",
|
|
198
|
+
"transition_determinism": True,
|
|
199
|
+
"unmatched_event": "ignored_state_unchanged",
|
|
200
|
+
"output_semantics": "final_state_only",
|
|
201
|
+
},
|
|
202
|
+
"forbidden": [
|
|
203
|
+
"在 output 语义位放中途产物(output 仅到达 final state 时存在)",
|
|
204
|
+
"直接改 context(immutable,仅 assign 更新)",
|
|
205
|
+
"断言未匹配事件会运行时报错(XState v5 现实是静默忽略+state.can() 为 false——非法组合的表达位是 transition contract 声明与 can() 守卫位)",
|
|
206
|
+
],
|
|
207
|
+
"x-research-anchors": {
|
|
208
|
+
"note": "【待 Owner 裁定·差异表 #7】PRD「Illegal Transition 必须可表达」在 XState v5(npm 5.32.6)无对应词形:未匹配/未启用事件=「no enabled transition → state does not change」静默忽略,state.can() 显式守卫为唯一查询位。本物料落 PRD 语义意图(非法组合经 transition contract 显式声明)+实现绑定注记 can() 守卫位;是否以治理层概念保留 Illegal Transition 词形待裁定。六概念词形与 guard 序列化命名推荐(reusability+visualization)均为 stately.ai 官方文档 2026-09-03 实抓",
|
|
209
|
+
"sources": [
|
|
210
|
+
{"url": "https://stately.ai/docs/transitions", "fetched": FETCH},
|
|
211
|
+
{"url": "https://stately.ai/docs/guards", "fetched": FETCH},
|
|
212
|
+
{"url": "https://stately.ai/docs/input", "fetched": FETCH},
|
|
213
|
+
{"url": "https://stately.ai/docs/output", "fetched": FETCH},
|
|
214
|
+
{"url": "https://registry.npmjs.org/xstate", "fetched": FETCH},
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
materials["archetype.state.wizard.json"] = {
|
|
220
|
+
"id": "STATE_ARCHETYPE.WIZARD",
|
|
221
|
+
"kind": "archetype",
|
|
222
|
+
"layer": "PATTERN",
|
|
223
|
+
"title_zh": "分步向导状态机",
|
|
224
|
+
"summary_zh": "线性/分支多步流向导原型(XState 六概念承载):步骤推进建模为嵌套 statechart,next/prev 事件经 guard 把关(如 stepValid),targeted self-transition 重置子状态的官方坑位写入已知风险。",
|
|
225
|
+
"semantic": {
|
|
226
|
+
"responsibility": "多步流程的步骤位置、每步合法性与推进事件的单点声明",
|
|
227
|
+
"when_to_use": "线性/分支多步流(分步创建向导类)——步骤间有顺序与守卫依赖(on: {next: {guard: 'stepValid', target: ...}} 模式,XState 六概念承载)",
|
|
228
|
+
"when_not_to_use": "无顺序依赖的自由表单(STATE_ARCHETYPE.FORM_EDIT);远端取数(STATE_ARCHETYPE.SERVER_QUERY)",
|
|
229
|
+
},
|
|
230
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
231
|
+
"defaults": {
|
|
232
|
+
"step_transition": "guarded",
|
|
233
|
+
"child_state_reset_on_targeted_self_transition": True,
|
|
234
|
+
"vocabulary": ["state", "event", "transition", "guard", "actor", "input", "output"],
|
|
235
|
+
},
|
|
236
|
+
"known_risks": [
|
|
237
|
+
"targeted self-transition 重置子状态(只想执行动作保留子状态必须用 targetless transition——官方文档实抓坑位)",
|
|
238
|
+
],
|
|
239
|
+
"x-research-anchors": {
|
|
240
|
+
"note": "XState v5 嵌套态/self-transition 子状态重置/targetless 语义为 stately.ai transitions/states 页 2026-09-03 实抓(差异表 #1 判定:八值词形可承载、无冲突)",
|
|
241
|
+
"sources": [
|
|
242
|
+
{"url": "https://stately.ai/docs/transitions", "fetched": FETCH},
|
|
243
|
+
{"url": "https://stately.ai/docs/states", "fetched": FETCH},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
materials["archetype.state.optimistic_mutation.json"] = {
|
|
249
|
+
"id": "STATE_ARCHETYPE.OPTIMISTIC_MUTATION",
|
|
250
|
+
"kind": "archetype",
|
|
251
|
+
"layer": "PATTERN",
|
|
252
|
+
"title_zh": "乐观更新 mutation",
|
|
253
|
+
"summary_zh": "写操作的乐观更新原型(TanStack Query v5 官方链序实抓):onMutate 取消在飞 refetch→快照→乐观写入→返回快照;onError 回滚;onSettled 无条件 invalidate 并保持 pending 至 refetch 完成。",
|
|
254
|
+
"semantic": {
|
|
255
|
+
"responsibility": "把「先显示后确认」的写路径标准化为五步链序,rollback 与补捞(invalidate)不靠手写自觉",
|
|
256
|
+
"when_to_use": "多处联动感知写结果的 cache 路线(§17「远端资源」判定的写侧);单处展示的临时项走 variables/isPending 的 UI 路线(免 rollback)——官方「When to use what」决策规则",
|
|
257
|
+
"when_not_to_use": "非远端同步的本地草稿(STATE_ARCHETYPE.FORM_EDIT);无并发覆盖风险的低频写(直接 invalidate 亦可)",
|
|
258
|
+
},
|
|
259
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
260
|
+
"defaults": {
|
|
261
|
+
"sequence": ["cancel_inflight_refetch", "snapshot", "optimistic_write", "on_error_rollback", "on_settled_invalidate"],
|
|
262
|
+
"sequence_note": "cancelQueries→getQueryData 快照→setQueryData→onError 回滚→onSettled 无条件 invalidateQueries(return promise 保持 pending 至 refetch 完成)——官方链序原样",
|
|
263
|
+
"invalidate_on_settled": True,
|
|
264
|
+
"await_invalidation": True,
|
|
265
|
+
"dual_route_note": "官方两路线:单处展示用 variables/isPending 的 UI 路线(无需 rollback);多处联动用 cache 路线(本链序)",
|
|
266
|
+
},
|
|
267
|
+
"forbidden": [
|
|
268
|
+
"跳过 cancelQueries 直接写缓存(在飞 refetch 会覆盖乐观值)",
|
|
269
|
+
"只在 onError invalidate 而 onSettled 缺失(成功路径漏 refetch)",
|
|
270
|
+
"rollback 后不 invalidate",
|
|
271
|
+
],
|
|
272
|
+
"x-research-anchors": {
|
|
273
|
+
"note": "五步链序与「onSettled 无条件 invalidate+return promise 保持 pending」为 TanStack Query v5 optimistic-updates/mutations 官方文档 2026-09-03 实抓(现行回调签名带 context 尾参)",
|
|
274
|
+
"sources": [
|
|
275
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates.md", "fetched": FETCH},
|
|
276
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/mutations.md", "fetched": FETCH},
|
|
277
|
+
],
|
|
278
|
+
},
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
materials["archetype.state.background_refresh.json"] = {
|
|
282
|
+
"id": "STATE_ARCHETYPE.BACKGROUND_REFRESH",
|
|
283
|
+
"kind": "archetype",
|
|
284
|
+
"layer": "PATTERN",
|
|
285
|
+
"title_zh": "后台刷新状态",
|
|
286
|
+
"summary_zh": "stale-while-revalidate 后台刷新原型(TanStack v5 默认档):staleTime 0 缓存即换,挂载/窗口聚焦/断线重连三触发自动 refetch;invalidateQueries 标 stale 并对渲染中查询后台补捞。",
|
|
287
|
+
"semantic": {
|
|
288
|
+
"responsibility": "远端缓存的过期判定与自动补捞触发面(mount/window_focus/reconnect 三触发+语义化 invalidation)",
|
|
289
|
+
"when_to_use": "STATE_ARCHETYPE.SERVER_QUERY 承载的远端资源的默认保鲜策略——mutation 后语义化 invalidation(前缀匹配 query key)也在本原型表达",
|
|
290
|
+
"when_not_to_use": "永不刷新的静态参照表(staleTime:'static'——invalidateQueries 对其无效);仅一次性取数",
|
|
291
|
+
},
|
|
292
|
+
"composition": {"requires": [], "optional": ["STATE_ARCHETYPE.SERVER_QUERY"], "incompatible": []},
|
|
293
|
+
"defaults": {
|
|
294
|
+
"refetch_on": ["mount", "window_focus", "reconnect"],
|
|
295
|
+
"refetch_on_window_focus": True,
|
|
296
|
+
"invalidate_overrides_staleTime": True,
|
|
297
|
+
"invalidate_semantics": "标 stale+渲染中才后台 refetch(前缀匹配/exact:true/predicate)",
|
|
298
|
+
},
|
|
299
|
+
"forbidden": [
|
|
300
|
+
"假设 invalidateQueries 必发即时请求(仅标记 stale,正在渲染才后台 refetch)",
|
|
301
|
+
],
|
|
302
|
+
"x-research-anchors": {
|
|
303
|
+
"note": "三触发默认与 invalidateQueries「覆盖 staleTime+渲染中才 refetch」语义为 TanStack Query v5 important-defaults/query-invalidation 官方文档 2026-09-03 实抓;与 SERVER_QUERY 经 composition.optional 互链(批次 2 组合链边)",
|
|
304
|
+
"sources": [
|
|
305
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults.md", "fetched": FETCH},
|
|
306
|
+
{"url": "https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation.md", "fetched": FETCH},
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
# ============================================================
|
|
312
|
+
# FRONTEND_ARCHETYPE 三型(v0.6.1 §18 逐字;layer=ARCHETYPE)
|
|
313
|
+
# ============================================================
|
|
314
|
+
|
|
315
|
+
materials["archetype.frontend.spa_layered.json"] = {
|
|
316
|
+
"id": "FRONTEND_ARCHETYPE.SPA_LAYERED",
|
|
317
|
+
"kind": "archetype",
|
|
318
|
+
"layer": "ARCHETYPE",
|
|
319
|
+
"title_zh": "分层 SPA 架构原型",
|
|
320
|
+
"summary_zh": "按稳定语义分层的单页应用架构原型:Page/Feature/Domain/API/Shared 五层共同稳定语义(PRD §18 逐字),依赖严格向下,层可选不强制齐备。",
|
|
321
|
+
"semantic": {
|
|
322
|
+
"responsibility": "以五层共同稳定语义承载 SPA 横向切分:页面/用例/领域模型/基础设施/共享件各归其位",
|
|
323
|
+
"when_to_use": "团队按层协作、领域模型复杂度需要独立承载的 SPA(v0.6.1 §18 共同稳定语义五层逐字:Page/Feature/Domain/API/Shared)",
|
|
324
|
+
"when_not_to_use": "按业务特性纵向切分优先的工程(FRONTEND_ARCHETYPE.FEATURE_ORIENTED);小到无需分层的模块化页面集(FRONTEND_ARCHETYPE.MODULAR——本原型与其互斥)",
|
|
325
|
+
},
|
|
326
|
+
"composition": {"requires": [], "optional": [], "incompatible": ["FRONTEND_ARCHETYPE.MODULAR"]},
|
|
327
|
+
"defaults": {
|
|
328
|
+
"layers_prd": ["Page", "Feature", "Domain", "API", "Shared"],
|
|
329
|
+
"dependency_rule": "strictly_downward",
|
|
330
|
+
"layers_optional_note": "项目不一定需要所有层(§18 逐字)",
|
|
331
|
+
"layer_object_example": "§19 Layer Object:Domain 的 allowed_dependencies=[SHARED]/forbidden_dependencies=[PAGE]/public_api_required=true",
|
|
332
|
+
},
|
|
333
|
+
"forbidden": [
|
|
334
|
+
"Domain 依赖 Page(§19 Layer Object forbidden_dependencies 逐字)",
|
|
335
|
+
"下层 import 上层",
|
|
336
|
+
],
|
|
337
|
+
"x-research-anchors": {
|
|
338
|
+
"note": "「项目不一定需要所有层」为 PRD §18 逐字;与 FSD「You don't have to use every layer」逐字同向(frontend-state-references.md 题 6/差异表 #4,2026-09-03 实抓)",
|
|
339
|
+
"sources": [
|
|
340
|
+
{"url": PRD_DOC_REF + " §18", "fetched": FETCH},
|
|
341
|
+
{"url": "https://feature-sliced.design/docs/reference/layers", "fetched": FETCH},
|
|
342
|
+
],
|
|
343
|
+
},
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
materials["archetype.frontend.feature_oriented.json"] = {
|
|
347
|
+
"id": "FRONTEND_ARCHETYPE.FEATURE_ORIENTED",
|
|
348
|
+
"kind": "archetype",
|
|
349
|
+
"layer": "ARCHETYPE",
|
|
350
|
+
"title_zh": "特性导向架构原型",
|
|
351
|
+
"summary_zh": "按业务特性纵向切分的架构原型(FSD 现行词形锚定):App/Pages/Widgets/Features/Entities/Shared 六有效层(Processes 已官方 deprecated),PRD 五稳定语义映射其上,slice 内只能 import 严格下层。",
|
|
352
|
+
"semantic": {
|
|
353
|
+
"responsibility": "以业务特性(feature slice)为第一切分轴,公共面下沉 Shared,实体面独立 Entities",
|
|
354
|
+
"when_to_use": "特性可高内聚切分、跨特性复用需要显式公共 API 门禁的工程(FSD import rule:每层只能依赖严格下层;App/Shared 为 layer=slice 例外)",
|
|
355
|
+
"when_not_to_use": "需要独立 Domain 横向层的分层 SPA(FRONTEND_ARCHETYPE.SPA_LAYERED);无需层约束的小型页面集(FRONTEND_ARCHETYPE.MODULAR)",
|
|
356
|
+
},
|
|
357
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
358
|
+
"defaults": {
|
|
359
|
+
"fsd_effective_layers": ["App", "Pages", "Widgets", "Features", "Entities", "Shared"],
|
|
360
|
+
"deprecated_layers": ["Processes"],
|
|
361
|
+
"prd_semantic_mapping": {"Page": "Pages", "Feature": "Features", "Domain": "Entities", "Shared": "Shared"},
|
|
362
|
+
"api_layer_note": "PRD 五语义的 API/Infrastructure 在 FSD 参照下无独立层——api 是各层 segment(entities/api、features/api、shared/api)",
|
|
363
|
+
"widgets_note": "FSD widgets 无 PRD 对应层——本原型下作为 optional 位",
|
|
364
|
+
"import_rule": "slice 内模块只能 import 严格下层的 slice;禁同层互引(FSD 的 @x 显式交叉引用机制仅 Entities 层合法)",
|
|
365
|
+
"public_api": "index_reexports_only",
|
|
366
|
+
"custom_layers": "forbidden",
|
|
367
|
+
},
|
|
368
|
+
"forbidden": [
|
|
369
|
+
"wildcard export(export *)",
|
|
370
|
+
"下层 import 上层",
|
|
371
|
+
"自造新层(FSD:层语义已标准化,不推荐新增)",
|
|
372
|
+
],
|
|
373
|
+
"x-research-anchors": {
|
|
374
|
+
"note": "【差异表 #4 部分差异】FSD 现行 7 层(Processes deprecated→有效 6 层)、无独立 API 层(api 是 segment)、widgets 无 PRD 对应、app 层 PRD 未纳入——四行声明随物料落位;import rule 严格向下与 Public API「contract+gate」定位(与 PRD §19 public_api_required 同构)为 feature-sliced.design 官方文档(v3 站点)2026-09-03 实抓",
|
|
375
|
+
"sources": [
|
|
376
|
+
{"url": "https://feature-sliced.design/docs/reference/layers", "fetched": FETCH},
|
|
377
|
+
{"url": "https://feature-sliced.design/docs/reference/public-api", "fetched": FETCH},
|
|
378
|
+
],
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
materials["archetype.frontend.modular.json"] = {
|
|
383
|
+
"id": "FRONTEND_ARCHETYPE.MODULAR",
|
|
384
|
+
"kind": "archetype",
|
|
385
|
+
"layer": "ARCHETYPE",
|
|
386
|
+
"title_zh": "模块化架构原型",
|
|
387
|
+
"summary_zh": "无强制分层的模块化架构原型:以页面/模块为自足单元,共享代码显式抽层,规模驱动演进——与 SPA_LAYERED 互斥(incompatible 双向登记)。",
|
|
388
|
+
"semantic": {
|
|
389
|
+
"responsibility": "以自足模块为切分单元承载小型/中型应用,不强制五层语义到位",
|
|
390
|
+
"when_to_use": "页面数量少、领域模型尚未复杂到需要独立 Domain/Feature 承载的工程——先模块化,规模触发再演进分层(「项目不一定需要所有层」的另一极端形态)",
|
|
391
|
+
"when_not_to_use": "需要层依赖约束治理的大型工程(SPA_LAYERED/FEATURE_ORIENTED)——本原型与 SPA_LAYERED 互斥",
|
|
392
|
+
},
|
|
393
|
+
"composition": {"requires": [], "optional": [], "incompatible": ["FRONTEND_ARCHETYPE.SPA_LAYERED"]},
|
|
394
|
+
"defaults": {"layering": "none_required", "shared_extraction": "explicit_only", "evolution": "scale_triggered"},
|
|
395
|
+
"x-research-anchors": {
|
|
396
|
+
"note": "互斥语义为本批次裁定(FRONTEND_ARCHETYPE.SPA_LAYERED×MODULAR incompatible 双向登记——incompatible 槽首个真实用例);「不必使用所有层」与 FSD「You don't have to use every layer」同向佐证模块化形态合法性(2026-09-03 实抓)",
|
|
397
|
+
"sources": [
|
|
398
|
+
{"url": PRD_DOC_REF + " §18", "fetched": FETCH},
|
|
399
|
+
{"url": "https://feature-sliced.design/docs/reference/layers", "fetched": FETCH},
|
|
400
|
+
],
|
|
401
|
+
},
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
# ============================================================
|
|
405
|
+
# FRONTEND_ARCHETYPE.ERROR_TAXONOMY(v0.6.1 §21 逐字九分型;layer=PATTERN)
|
|
406
|
+
# ============================================================
|
|
407
|
+
|
|
408
|
+
materials["archetype.frontend.error_taxonomy.json"] = {
|
|
409
|
+
"id": "FRONTEND_ARCHETYPE.ERROR_TAXONOMY",
|
|
410
|
+
"kind": "archetype",
|
|
411
|
+
"layer": "PATTERN",
|
|
412
|
+
"title_zh": "前端错误分类",
|
|
413
|
+
"summary_zh": "前端错误九分型逐字闭包(PRD §21):每型绑定呈现/重试/遥测/用户话术四语义位;浏览器原生信号只够两分,细分映射责任在 HTTP Client 适配层。",
|
|
414
|
+
"semantic": {
|
|
415
|
+
"responsibility": "把运行时错误归类为九分型闭包,驱动呈现/重试/遥测/话术四列的确定性处置",
|
|
416
|
+
"when_to_use": "任何触发 HTTP/异步调用的页面组契约错误处置面——错误到分型的映射在 HTTP Client 适配层完成(WHATWG fetch 原生只给 TypeError 与 HTTP status 两分,§21 九分型的映射责任不在浏览器)",
|
|
417
|
+
"when_not_to_use": "非错误态的加载/空态呈现;后端错误信封字段结构本身(v0.6.1 §44 Error Archetype 承载 type/title/status/detail/instance 等成员)",
|
|
418
|
+
},
|
|
419
|
+
"composition": {"requires": [], "optional": [], "incompatible": []},
|
|
420
|
+
"categories": {
|
|
421
|
+
"TRANSPORT": {
|
|
422
|
+
"presentation_pattern": "error_banner_with_retry",
|
|
423
|
+
"retry_behavior": "retryable_exponential_backoff",
|
|
424
|
+
"telemetry": "error_event_with_network_detail",
|
|
425
|
+
"user_message": "网络连接异常,请稍后重试",
|
|
426
|
+
},
|
|
427
|
+
"AUTHENTICATION": {
|
|
428
|
+
"presentation_pattern": "redirect_to_login",
|
|
429
|
+
"retry_behavior": "never_retry_auto",
|
|
430
|
+
"telemetry": "auth_event_401",
|
|
431
|
+
"user_message": "登录已过期,请重新登录",
|
|
432
|
+
},
|
|
433
|
+
"AUTHORIZATION": {
|
|
434
|
+
"presentation_pattern": "forbidden_page",
|
|
435
|
+
"retry_behavior": "never_retry",
|
|
436
|
+
"telemetry": "authz_event_403",
|
|
437
|
+
"user_message": "没有执行该操作的权限",
|
|
438
|
+
},
|
|
439
|
+
"VALIDATION": {
|
|
440
|
+
"presentation_pattern": "inline_field_error",
|
|
441
|
+
"retry_behavior": "no_retry_fix_input",
|
|
442
|
+
"telemetry": "warn_event_400_422",
|
|
443
|
+
"user_message": "表单内容有误,请按提示修正",
|
|
444
|
+
},
|
|
445
|
+
"BUSINESS": {
|
|
446
|
+
"presentation_pattern": "message_toast",
|
|
447
|
+
"retry_behavior": "no_retry_rule_rejected",
|
|
448
|
+
"telemetry": "business_code_event",
|
|
449
|
+
"user_message": "按业务规则返回的提示(RFC 9457 type URI/extension member 承载——detail 不可机器解析)",
|
|
450
|
+
},
|
|
451
|
+
"CONFLICT": {
|
|
452
|
+
"presentation_pattern": "refresh_or_merge_prompt",
|
|
453
|
+
"retry_behavior": "no_auto_retry_reload_first",
|
|
454
|
+
"telemetry": "conflict_event_409",
|
|
455
|
+
"user_message": "数据已被他人修改,请刷新后重试",
|
|
456
|
+
},
|
|
457
|
+
"TIMEOUT": {
|
|
458
|
+
"presentation_pattern": "timeout_toast_with_retry",
|
|
459
|
+
"retry_behavior": "retryable_bounded",
|
|
460
|
+
"telemetry": "timeout_event",
|
|
461
|
+
"user_message": "请求超时,请重试",
|
|
462
|
+
},
|
|
463
|
+
"OFFLINE": {
|
|
464
|
+
"presentation_pattern": "offline_banner_persistent",
|
|
465
|
+
"retry_behavior": "auto_resume_on_reconnect",
|
|
466
|
+
"telemetry": "offline_event",
|
|
467
|
+
"user_message": "当前离线,恢复网络后自动同步",
|
|
468
|
+
},
|
|
469
|
+
"UNKNOWN": {
|
|
470
|
+
"presentation_pattern": "generic_error_page",
|
|
471
|
+
"retry_behavior": "no_auto_retry",
|
|
472
|
+
"telemetry": "unclassified_event",
|
|
473
|
+
"user_message": "出了点问题,请稍后重试",
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
"constraints": [
|
|
477
|
+
"浏览器原生信号只够两分:WHATWG fetch 网络失败 reject TypeError、HTTP 错误状态不 reject(查 Response.status)——TIMEOUT/OFFLINE/AUTHENTICATION 等细分全部依赖 client 适配层信号(axios code/AbortSignal/navigator.onLine/status 映射)",
|
|
478
|
+
"九分型映射责任在 HTTP Client Archetype 层而非浏览器",
|
|
479
|
+
"RFC 9457 about:blank(未给出更具体类型时的缺省)与 UNKNOWN 同构",
|
|
480
|
+
],
|
|
481
|
+
"x-research-anchors": {
|
|
482
|
+
"note": "【待 Owner 裁定·差异表 #8 两项】①是否补 CANCELED 第十分型(axios ERR_CANCELED/fetch AbortError/TanStack cancelQueries 三处业界共识,retry 语义绝不重试——九分型缺位会把取消误归 UNKNOWN/TRANSPORT)②429 归属(ofetch 默认重试列表含 409/429 视作传输层瞬时错误,与 CONFLICT 语义有张力)——本物料保持九分型不扩,待裁定后走词汇表式修订。WHATWG fetch TypeError/RFC 9457 成员空间/axios error codes 全表/ofetch 重试列表为规范与官方文档 2026-09-03 实抓",
|
|
483
|
+
"sources": [
|
|
484
|
+
{"url": "https://fetch.spec.whatwg.org/", "fetched": FETCH},
|
|
485
|
+
{"url": "https://www.rfc-editor.org/rfc/rfc9457.txt", "fetched": FETCH},
|
|
486
|
+
{"url": "https://axios.rest/pages/advanced/error-handling", "fetched": FETCH},
|
|
487
|
+
{"url": "https://github.com/unjs/ofetch", "fetched": FETCH},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def main():
|
|
494
|
+
os.makedirs(OUT, exist_ok=True)
|
|
495
|
+
for name, body in materials.items():
|
|
496
|
+
path = os.path.join(OUT, name)
|
|
497
|
+
with open(path, "w", encoding="utf-8", newline="\n") as f:
|
|
498
|
+
json.dump(body, f, ensure_ascii=False, indent=2)
|
|
499
|
+
f.write("\n")
|
|
500
|
+
print("wrote", name, "id=", body["id"])
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
if __name__ == "__main__":
|
|
504
|
+
main()
|