pomaster 0.1.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/COMMERCIAL_LICENSE.md +35 -0
- package/LICENSE +83 -0
- package/README.md +396 -0
- package/SECURITY.md +22 -0
- package/TRADEMARKS.md +12 -0
- package/catalog/candidates/candidates-draft.json +198 -0
- package/catalog/candidates/rejected.json +422 -0
- package/catalog/catalog-lock.draft.json +822 -0
- package/catalog/gates/gate.be.api.contract_checks.json +138 -0
- package/catalog/gates/gate.be.chg.contract_change_checks.json +138 -0
- package/catalog/gates/gate.chg.prechange_checks.json +155 -0
- package/catalog/gates/gate.web.api.request_checks.json +149 -0
- package/catalog/gates/gate.web.grid.checks.json +149 -0
- package/catalog/knowledge/knowledge.api.example_stable_error_code.json +80 -0
- package/catalog/knowledge/knowledge.chg.example_compat_window.json +87 -0
- package/catalog/knowledge/knowledge.chg.example_prop_migration.json +87 -0
- package/catalog/knowledge/knowledge.fp.api.field_drift_no_contract.json +83 -0
- package/catalog/knowledge/knowledge.fp.api.per_page_http_client.json +83 -0
- package/catalog/knowledge/knowledge.fp.be.contract_drift.json +87 -0
- package/catalog/knowledge/knowledge.fp.chg.page_local_padding.json +88 -0
- package/catalog/knowledge/knowledge.fp.grid.global_td_width.json +87 -0
- package/catalog/knowledge/knowledge.web.api.example_get_entity_list.json +83 -0
- package/catalog/knowledge/knowledge.web.grid.example_column_preset.json +83 -0
- package/catalog/policies/authority.be.api_contract_ownership.json +77 -0
- package/catalog/policies/authority.be.contract_ownership.json +73 -0
- package/catalog/policies/authority.chg.change_owners.json +75 -0
- package/catalog/policies/authority.web.api.request_owners.json +82 -0
- package/catalog/policies/authority.web.grid.ownership.json +78 -0
- package/catalog/policies/policy.api.backward_compat_defaults.json +83 -0
- package/catalog/policies/policy.api.contract_impl_consistency.json +81 -0
- package/catalog/policies/policy.api.no_informal_contract.json +82 -0
- package/catalog/policies/policy.arch.decision_tradeoff_record.json +78 -0
- package/catalog/policies/policy.cache.lifecycle_definition.json +79 -0
- package/catalog/policies/policy.chg.affect_templates.json +79 -0
- package/catalog/policies/policy.chg.breaking_versioning.json +81 -0
- package/catalog/policies/policy.chg.compat_migration_rollback.json +82 -0
- package/catalog/policies/policy.chg.deprecate_before_delete.json +82 -0
- package/catalog/policies/policy.chg.fix_at_root_cause_level.json +78 -0
- package/catalog/policies/policy.chg.observable_evolution.json +78 -0
- package/catalog/policies/policy.chg.prechange_consumer_scan.json +83 -0
- package/catalog/policies/policy.chg.staged_rollout.json +79 -0
- package/catalog/policies/policy.chg.sync_contract_docs_tests.json +81 -0
- package/catalog/policies/policy.conflict.priority_ladder.json +79 -0
- package/catalog/policies/policy.dep.admission_six_dimension_check.json +84 -0
- package/catalog/policies/policy.dep.change_surface_review.json +82 -0
- package/catalog/policies/policy.dep.introduction_review.json +83 -0
- package/catalog/policies/policy.derived.single_implementation.json +77 -0
- package/catalog/policies/policy.obs.correlation_context_minimum.json +81 -0
- package/catalog/policies/policy.obs.rum_dimension_whitelist.json +77 -0
- package/catalog/policies/policy.proc.pre_code_declaration.json +78 -0
- package/catalog/policies/policy.rel.pre_release_confirmation.json +77 -0
- package/catalog/policies/policy.role.domain_decision_authority.json +77 -0
- package/catalog/policies/policy.sec.third_party_execution_register.json +78 -0
- package/catalog/policies/policy.spec.admission_criteria.json +79 -0
- package/catalog/policies/policy.spec.derived_view_regeneration.json +79 -0
- package/catalog/policies/policy.spec.draft_not_baseline.json +77 -0
- package/catalog/policies/policy.spec.file_structure_contract.json +76 -0
- package/catalog/policies/policy.spec.metadata_required.json +76 -0
- package/catalog/policies/policy.spec.post_dev_backfill_classify.json +74 -0
- package/catalog/policies/policy.spec.procedural_record_not_surrogate.json +76 -0
- package/catalog/policies/policy.spec.semantic_identity.json +77 -0
- package/catalog/policies/policy.spec.unresolved_ledger_gate.json +79 -0
- package/catalog/policies/policy.stack.no_implicit_selection.json +77 -0
- package/catalog/policies/policy.tool.scoped_scan_boundary.json +78 -0
- package/catalog/policies/policy.web.api.auth_app_client_split.json +93 -0
- package/catalog/policies/policy.web.api.client_change_impact.json +86 -0
- package/catalog/policies/policy.web.api.domain_api_only.json +84 -0
- package/catalog/policies/policy.web.api.error_normalization.json +82 -0
- package/catalog/policies/policy.web.api.generated_client.json +82 -0
- package/catalog/policies/policy.web.api.late_result_guard.json +80 -0
- package/catalog/policies/policy.web.api.mutation_idempotency.json +84 -0
- package/catalog/policies/policy.web.api.no_network_optimism.json +82 -0
- package/catalog/policies/policy.web.api.query_cancel_stale_drop.json +80 -0
- package/catalog/policies/policy.web.api.request_infrastructure.json +95 -0
- package/catalog/policies/policy.web.api.retry_discipline.json +87 -0
- package/catalog/policies/policy.web.api.session_recovery_split.json +94 -0
- package/catalog/policies/policy.web.api.single_http_client.json +88 -0
- package/catalog/policies/policy.web.api.single_loading_source.json +81 -0
- package/catalog/policies/policy.web.api.transport_vs_business.json +81 -0
- package/catalog/policies/policy.web.api.trusted_endpoint_source.json +82 -0
- package/catalog/policies/policy.web.api.typed_domain_naming.json +79 -0
- package/catalog/policies/policy.web.arch.layer_isolation.json +376 -0
- package/catalog/policies/policy.web.arch.naming_conventions.json +207 -0
- package/catalog/policies/policy.web.arch.public_api_barrel.json +134 -0
- package/catalog/policies/policy.web.chg.controlled_change_triggers.json +79 -0
- package/catalog/policies/policy.web.copy.suppression_ledger_discipline.json +78 -0
- package/catalog/policies/policy.web.grid.column_schema_fields.json +78 -0
- package/catalog/policies/policy.web.grid.config_isolation.json +78 -0
- package/catalog/policies/policy.web.grid.freeze_key_columns.json +77 -0
- package/catalog/policies/policy.web.grid.interaction_registry.json +80 -0
- package/catalog/policies/policy.web.grid.keyboard_clipboard.json +79 -0
- package/catalog/policies/policy.web.grid.schema_driven_shell.json +81 -0
- package/catalog/policies/policy.web.grid.schema_versioning.json +78 -0
- package/catalog/policies/policy.web.grid.server_ops_virtualization.json +81 -0
- package/catalog/policies/policy.web.grid.shell_change_matrix.json +76 -0
- package/catalog/policies/policy.web.grid.width_fix_ladder.json +79 -0
- package/catalog/policies/policy.web.perf.budget_skeleton.json +110 -0
- package/catalog/policies/policy.web.style.ownership_matrix.json +207 -0
- package/catalog/policies/policy.web.track.consent_lifecycle.json +78 -0
- package/catalog/policies/policy.web.track.privacy_default_deny.json +81 -0
- package/catalog/policies/policy.web.track.stable_event_keys.json +78 -0
- package/catalog/policies/policy.web.uiux.provider_evidence_not_business_truth.json +86 -0
- package/catalog/projection-presets/registry-tree.yaml +307 -0
- package/catalog/sensors/sensor.browser.deterministic.json +53 -0
- package/catalog/sensors/sensor.browser.interactive.json +58 -0
- package/catalog/sensors/sensor.build.static.json +45 -0
- package/catalog/sensors/sensor.contract.conformance.json +47 -0
- package/catalog/sensors/sensor.performance.budget.json +46 -0
- package/catalog/sensors/sensor.production.metric.json +44 -0
- package/catalog/tools/apply_human_review_pilot_0001.py +488 -0
- package/catalog/tools/materialize_batch4_uplift.py +776 -0
- package/catalog/tools/materialize_catalog_pilot.py +784 -0
- package/dist/bin.js +52362 -0
- package/legal/THIRD_PARTY_NOTICES.md +336 -0
- package/package.json +36 -0
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""语义分解试点 · catalog 条目物化 + lock 草案生成器(2026-08-28;pilot-0001 落账版)。
|
|
3
|
+
|
|
4
|
+
输入: catalog/candidates/candidates-draft.json(pilot-0001 已落 Human Review 处置:
|
|
5
|
+
每卡携带 review.disposition ∈ {ACCEPT, ADJUST, REJECT},落账脚本见同目录
|
|
6
|
+
apply_human_review_pilot_0001.py;REJECT 条目 fail-closed 跳过并归档于
|
|
7
|
+
catalog/candidates/rejected.json)
|
|
8
|
+
输出:
|
|
9
|
+
catalog/policies/<id 小写>.json — classification ∈ {UNIVERSAL_POLICY, LANE_POLICY}(45 条,
|
|
10
|
+
含 R-F 上提后 UNIVERSAL 22 / LANE 23)
|
|
11
|
+
catalog/knowledge/<id 小写>.json — KNOWLEDGE_PATTERN / FAILURE_PATTERN(10 条,advisory 永不 FAIL gate)
|
|
12
|
+
catalog/gates/<id 小写>.json — GATE_RECIPE(5 条,判卷步骤草案引用 03 GateResult 形态)
|
|
13
|
+
catalog/catalog-lock.draft.json — read-side 指纹(D24)
|
|
14
|
+
|
|
15
|
+
纪律(试点任务书 §93 + D24 + D5/B3):
|
|
16
|
+
- 产物全部是 PROPOSAL(source=design_seed, evidence=PLANNED),axes.lifecycle 保持 PROPOSED;
|
|
17
|
+
Human Review 处置记录于条目 review 字段(disposition/seq/ref),不改变生命周期轴
|
|
18
|
+
- 词表缺口只登记 x-vocab-pr 候选注记,禁止旁路改 vocab-lock(V1–V9 只登记不执行)
|
|
19
|
+
- R-C=b 裁决:CONTRACT_TEMPLATE 暂留 candidates-draft 不物化;gate 检查项③悬空引用已改内联字段清单
|
|
20
|
+
- R-D 裁决:GATE.CHG.PRECHANGE_CHECKS 检查项⑤为机器预检元数据字段存在(转机器派生)
|
|
21
|
+
- 幂等:同输入重跑 byte-stable(DEF-POM-002 教训);entries 按 id 排序
|
|
22
|
+
- W1-A2 P0.5-1 T3 标注战役(PRD v0.5.2 §5.2/§14;Owner 裁决 8 ② 2026-09-01):
|
|
23
|
+
applies_when 扩机器 applicability 字段(lanes 平移 / capabilities / change_classes /
|
|
24
|
+
applicability_note 降级位;保守派生——拿不准的留空回退 lane 缺省 O7 + x-applicability-review
|
|
25
|
+
注记 human-review 候选);catalog-lock 改为合并重锁(60 条命名空间置换,基线零触碰),
|
|
26
|
+
不再整体覆写(batch4/SPEC-D/W1-E 已把 lock 推到 100 entries)
|
|
27
|
+
"""
|
|
28
|
+
import hashlib
|
|
29
|
+
import json
|
|
30
|
+
import os
|
|
31
|
+
import sys
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # .../catalog
|
|
39
|
+
CANDIDATES_PATH = os.path.join(ROOT, "candidates", "candidates-draft.json")
|
|
40
|
+
|
|
41
|
+
PILOT_DATE = "2026-08-28"
|
|
42
|
+
CAPTURED_BY = "agent:claude/semantic-decomposition-pilot"
|
|
43
|
+
|
|
44
|
+
with open(CANDIDATES_PATH, encoding="utf-8") as f:
|
|
45
|
+
records = json.load(f)
|
|
46
|
+
|
|
47
|
+
candidates = [r for r in records if isinstance(r, dict) and "candidate_id" in r]
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------- titles(人工拟定短题)
|
|
50
|
+
TITLES = {
|
|
51
|
+
# UNIVERSAL_POLICY (22,含 R-F 上提 2 条)
|
|
52
|
+
"POLICY.CHG.PRECHANGE_CONSUMER_SCAN": "公共能力变更前影响面扫描",
|
|
53
|
+
"POLICY.CHG.COMPAT_MIGRATION_ROLLBACK": "公共变更兼容或附迁移回滚",
|
|
54
|
+
"POLICY.CHG.SYNC_CONTRACT_DOCS_TESTS": "变更落地同步契约文档测试",
|
|
55
|
+
"POLICY.CHG.DEPRECATE_BEFORE_DELETE": "先弃用确认无使用方后删除",
|
|
56
|
+
"POLICY.CHG.FIX_AT_ROOT_CAUSE_LEVEL": "按根因层级修复缺陷",
|
|
57
|
+
"POLICY.SPEC.METADATA_REQUIRED": "spec 元数据必填",
|
|
58
|
+
"POLICY.SPEC.POST_DEV_BACKFILL_CLASSIFY": "开发后规则回填显式归类",
|
|
59
|
+
"POLICY.SPEC.DRAFT_NOT_BASELINE": "Draft 不得当作 Baseline 执行",
|
|
60
|
+
"POLICY.CHG.AFFECT_TEMPLATES": "变更影响评估工具化",
|
|
61
|
+
"POLICY.CHG.STAGED_ROLLOUT": "公共变更三阶段推进",
|
|
62
|
+
"AUTHORITY.CHG.CHANGE_OWNERS": "变更权威分配默认值",
|
|
63
|
+
"POLICY.CHG.BREAKING_VERSIONING": "Breaking Change 版本化与事后补齐",
|
|
64
|
+
"AUTHORITY.WEB.API.REQUEST_OWNERS": "请求层权威分配默认值",
|
|
65
|
+
"AUTHORITY.WEB.GRID.OWNERSHIP": "表格权威分配默认值",
|
|
66
|
+
"POLICY.CHG.OBSERVABLE_EVOLUTION": "契约演进可并行可观测可撤回",
|
|
67
|
+
"AUTHORITY.BE.CONTRACT_OWNERSHIP": "契约提供方管兼容消费方确认迁移",
|
|
68
|
+
"POLICY.API.CONTRACT_IMPL_CONSISTENCY": "契约与实现一致性",
|
|
69
|
+
"POLICY.API.NO_INFORMAL_CONTRACT": "禁止非正式契约来源",
|
|
70
|
+
"POLICY.API.BACKWARD_COMPAT_DEFAULTS": "接口演进默认向后兼容",
|
|
71
|
+
"AUTHORITY.BE.API_CONTRACT_OWNERSHIP": "后端管服务端契约消费方确认联调",
|
|
72
|
+
# LANE_POLICY (23,R-F 上提后)
|
|
73
|
+
"POLICY.WEB.CHG.CONTROLLED_CHANGE_TRIGGERS": "Baseline 冻结后受控变更触发清单",
|
|
74
|
+
"POLICY.WEB.API.DOMAIN_API_ONLY": "页面只经 Domain API 调用",
|
|
75
|
+
"POLICY.WEB.API.SINGLE_HTTP_CLIENT": "HTTP Client 单点统一",
|
|
76
|
+
"POLICY.WEB.API.TYPED_DOMAIN_NAMING": "请求函数类型化与领域命名",
|
|
77
|
+
"POLICY.WEB.API.QUERY_CANCEL_STALE_DROP": "查询可取消并丢弃过期响应",
|
|
78
|
+
"POLICY.WEB.API.MUTATION_IDEMPOTENCY": "mutation 显式幂等与重试边界",
|
|
79
|
+
"POLICY.WEB.API.ERROR_NORMALIZATION": "错误统一结构后上抛",
|
|
80
|
+
"POLICY.WEB.API.TRANSPORT_VS_BUSINESS": "传输成功与业务成功分判",
|
|
81
|
+
"POLICY.WEB.API.RETRY_DISCIPLINE": "重试服从幂等与 Retry-After 纪律",
|
|
82
|
+
"POLICY.WEB.API.LATE_RESULT_GUARD": "过期结果写回防护",
|
|
83
|
+
"POLICY.WEB.API.TRUSTED_ENDPOINT_SOURCE": "endpoint 只来自受控来源",
|
|
84
|
+
"POLICY.WEB.API.NO_NETWORK_OPTIMISM": "禁『在线即成功』传输假设",
|
|
85
|
+
"POLICY.WEB.API.GENERATED_CLIENT": "契约优先生成客户端",
|
|
86
|
+
"POLICY.WEB.API.SINGLE_LOADING_SOURCE": "loading 状态单一来源",
|
|
87
|
+
"POLICY.WEB.API.CLIENT_CHANGE_IMPACT": "客户端公共变更影响评估",
|
|
88
|
+
"POLICY.WEB.GRID.SCHEMA_DRIVEN_SHELL": "表格 schema 驱动渲染",
|
|
89
|
+
"POLICY.WEB.GRID.COLUMN_SCHEMA_FIELDS": "列 schema 六字段必填",
|
|
90
|
+
"POLICY.WEB.GRID.SERVER_OPS_VIRTUALIZATION": "大数据量服务端操作与虚拟化",
|
|
91
|
+
"POLICY.WEB.GRID.CONFIG_ISOLATION": "列配置四维隔离",
|
|
92
|
+
"POLICY.WEB.GRID.WIDTH_FIX_LADDER": "列宽修复影响层级阶梯",
|
|
93
|
+
"POLICY.WEB.GRID.SHELL_CHANGE_MATRIX": "表格壳变更全类型回归",
|
|
94
|
+
"POLICY.WEB.GRID.INTERACTION_REGISTRY": "表格交互逐项登记绑定",
|
|
95
|
+
"POLICY.WEB.GRID.FREEZE_KEY_COLUMNS": "冻结关键列与宽度预算",
|
|
96
|
+
"POLICY.WEB.GRID.KEYBOARD_CLIPBOARD": "键盘与剪贴板契约",
|
|
97
|
+
"POLICY.WEB.GRID.SCHEMA_VERSIONING": "列 schema 与保存视图版本化",
|
|
98
|
+
# KNOWLEDGE_PATTERN / FAILURE_PATTERN (10)
|
|
99
|
+
"KNOWLEDGE.CHG.EXAMPLE_PROP_MIGRATION": "示例:props 加法式迁移",
|
|
100
|
+
"KNOWLEDGE.FP.CHG.PAGE_LOCAL_PADDING": "失败模式:页面局部改公共默认 padding",
|
|
101
|
+
"KNOWLEDGE.WEB.API.EXAMPLE_GET_ENTITY_LIST": "示例:getEntityList 传输不透明",
|
|
102
|
+
"KNOWLEDGE.FP.API.PER_PAGE_HTTP_CLIENT": "失败模式:每页自建请求实例",
|
|
103
|
+
"KNOWLEDGE.WEB.GRID.EXAMPLE_COLUMN_PRESET": "示例:报表共享列 preset",
|
|
104
|
+
"KNOWLEDGE.FP.GRID.GLOBAL_TD_WIDTH": "失败模式:全局 td 宽度 CSS 波及全站",
|
|
105
|
+
"KNOWLEDGE.CHG.EXAMPLE_COMPAT_WINDOW": "示例:兼容发布后再关旧版窗口",
|
|
106
|
+
"KNOWLEDGE.FP.BE.CONTRACT_DRIFT": "失败模式:只改实现不同步契约",
|
|
107
|
+
"KNOWLEDGE.API.EXAMPLE_STABLE_ERROR_CODE": "示例:稳定错误码加 TraceId",
|
|
108
|
+
"KNOWLEDGE.FP.API.FIELD_DRIFT_NO_CONTRACT": "失败模式:改字段不更新契约",
|
|
109
|
+
# GATE_RECIPE (5)
|
|
110
|
+
"GATE.CHG.PRECHANGE_CHECKS": "变更门禁检查单",
|
|
111
|
+
"GATE.WEB.API.REQUEST_CHECKS": "请求层门禁检查单",
|
|
112
|
+
"GATE.WEB.GRID.CHECKS": "表格门禁检查单",
|
|
113
|
+
"GATE.BE.CHG.CONTRACT_CHANGE_CHECKS": "契约变更五类消费者门禁",
|
|
114
|
+
"GATE.BE.API.CONTRACT_CHECKS": "API 契约五方同步门禁",
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# ---------------------------------------------------------------- gate 判卷步骤草案(引用 03 GateResult 形态)
|
|
118
|
+
GATE_CHECKS = {
|
|
119
|
+
"GATE.CHG.PRECHANGE_CHECKS": [
|
|
120
|
+
{"seq": 1, "check_id": "root_cause_level_declared",
|
|
121
|
+
"statement_zh": "根因层级明确:属公共缺陷不得以局部补丁了结,属局部问题不得擅动公共层",
|
|
122
|
+
"judgeability": "hybrid",
|
|
123
|
+
"machine_support": "change/task 对象 payload.class_scan_result(02 信封 R4 条件式)提供同类扫描留痕",
|
|
124
|
+
"manual_part": "公共 vs 局部的语义判定终审在人"},
|
|
125
|
+
{"seq": 2, "check_id": "consumer_list_complete",
|
|
126
|
+
"statement_zh": "调用方清单完整:直接与间接消费方均已枚举",
|
|
127
|
+
"judgeability": "hybrid",
|
|
128
|
+
"machine_support": "引用/调用图扫描可枚举候选消费方",
|
|
129
|
+
"manual_part": "清单完整性需 Owner 抽验"},
|
|
130
|
+
{"seq": 3, "check_id": "compat_migration_rollback_executable",
|
|
131
|
+
"statement_zh": "兼容、迁移、回滚方案可执行",
|
|
132
|
+
"judgeability": "human",
|
|
133
|
+
"manual_part": "方案可执行性为语义判断"},
|
|
134
|
+
{"seq": 4, "check_id": "tests_examples_docs_updated",
|
|
135
|
+
"statement_zh": "测试、示例、文档已同步更新并发出通知",
|
|
136
|
+
"judgeability": "machine",
|
|
137
|
+
"machine_support": "变更记录对象字段存在性 + 工作区 diff 扫描可机判"},
|
|
138
|
+
{"seq": 5, "check_id": "spec_metadata_registered",
|
|
139
|
+
"statement_zh": "机器预检:Spec 元数据字段存在(状态/版本/Owner/更新时间/生效范围)",
|
|
140
|
+
"judgeability": "machine",
|
|
141
|
+
"machine_support": "信封 axes/authority/sources 结构性派生承载,字段存在性可机判(pilot-0001 R-D 裁决:转机器派生)"},
|
|
142
|
+
{"seq": 6, "check_id": "post_dev_rule_backfill_classified",
|
|
143
|
+
"statement_zh": "开发后 Spec Update Review 已把新规则显式归类(需求级记录/长期 spec/通用规范候选/无需更新)",
|
|
144
|
+
"judgeability": "hybrid",
|
|
145
|
+
"machine_support": "归类字段非空可机判",
|
|
146
|
+
"manual_part": "归类正确性抽验"},
|
|
147
|
+
],
|
|
148
|
+
"GATE.WEB.API.REQUEST_CHECKS": [
|
|
149
|
+
{"seq": 1, "check_id": "domain_api_only",
|
|
150
|
+
"statement_zh": "页面仅使用 Domain API 函数发起请求",
|
|
151
|
+
"judgeability": "machine",
|
|
152
|
+
"machine_support": "静态扫描页面层 import 与 fetch/axios 直调"},
|
|
153
|
+
{"seq": 2, "check_id": "typed_and_unified_errors",
|
|
154
|
+
"statement_zh": "请求函数类型化且错误结构统一",
|
|
155
|
+
"judgeability": "hybrid",
|
|
156
|
+
"machine_support": "函数签名/错误类型引用存在性",
|
|
157
|
+
"manual_part": "类型语义一致性"},
|
|
158
|
+
{"seq": 3, "check_id": "cancel_retry_idempotency_declared",
|
|
159
|
+
"statement_zh": "取消、重试、幂等边界已显式声明",
|
|
160
|
+
"judgeability": "machine",
|
|
161
|
+
"machine_support": "请求函数契约字段存在性可机判(内联字段清单:StatusPolicy/Cancellation/Retry/RetryAfter/Idempotency)"},
|
|
162
|
+
{"seq": 4, "check_id": "no_duplicated_loading_auth",
|
|
163
|
+
"statement_zh": "无重复 loading 或认证逻辑",
|
|
164
|
+
"judgeability": "machine",
|
|
165
|
+
"machine_support": "模式扫描(多 client 实例创建/重复 token 刷新逻辑)"},
|
|
166
|
+
{"seq": 5, "check_id": "status_guard_endpoint_source_declared",
|
|
167
|
+
"statement_zh": "状态判定、旧结果防护与 endpoint 来源明确",
|
|
168
|
+
"judgeability": "hybrid",
|
|
169
|
+
"machine_support": "契约字段存在性(StatusPolicy/LateResultGuard/endpoint 来源声明)",
|
|
170
|
+
"manual_part": "声明与实际行为一致性"},
|
|
171
|
+
],
|
|
172
|
+
"GATE.WEB.GRID.CHECKS": [
|
|
173
|
+
{"seq": 1, "check_id": "schema_driven_rendering",
|
|
174
|
+
"statement_zh": "表格经统一表格壳 + typed Column Schema 渲染,无 template 手写列或复制列数组",
|
|
175
|
+
"judgeability": "machine",
|
|
176
|
+
"machine_support": "模板/渲染函数中列定义模式扫描"},
|
|
177
|
+
{"seq": 2, "check_id": "width_fix_level_correct",
|
|
178
|
+
"statement_zh": "列宽修复影响层级正确(单页例外→同类型 preset→领域 preset→表格壳→全局 token 逐级上浮)",
|
|
179
|
+
"judgeability": "human",
|
|
180
|
+
"manual_part": "层级选择语义判定"},
|
|
181
|
+
{"seq": 3, "check_id": "large_data_and_config_isolation_safe",
|
|
182
|
+
"statement_zh": "大数据量走服务端分页/筛选/排序 + 虚拟化;列配置按页面/表格/用户/schema 版本四维隔离",
|
|
183
|
+
"judgeability": "hybrid",
|
|
184
|
+
"machine_support": "分页/虚拟化配置存在性、配置 key 隔离扫描",
|
|
185
|
+
"manual_part": "『大数据』阈值属项目基线(PRD §93.5 拆分点:Catalog Policy vs Project Baseline)"},
|
|
186
|
+
{"seq": 4, "check_id": "export_matches_view",
|
|
187
|
+
"statement_zh": "导出内容与当前视图一致",
|
|
188
|
+
"judgeability": "machine",
|
|
189
|
+
"machine_support": "ExportScope 与当前视图状态对账"},
|
|
190
|
+
{"seq": 5, "check_id": "interaction_registered_and_bound",
|
|
191
|
+
"statement_zh": "每个支持交互已在 interaction-contract-registry 声明并绑定 action_id + api_requirement_ids",
|
|
192
|
+
"judgeability": "machine",
|
|
193
|
+
"machine_support": "registry 条目 ↔ 页面交互声明对账",
|
|
194
|
+
"not_configured_semantics": "opt-in:registry 文件不存在 → verdict=not_configured(终局性诚实报告),禁止静默通过——interaction-contract opt-in 门禁『文件不存在则门禁静默』是 directly blocked anti-case"},
|
|
195
|
+
],
|
|
196
|
+
"GATE.BE.CHG.CONTRACT_CHANGE_CHECKS": [
|
|
197
|
+
{"seq": 1, "check_id": "api_consumers_checked", "statement_zh": "API 类消费者已检查", "judgeability": "machine",
|
|
198
|
+
"machine_support": "五类消费者为封闭枚举,可逐类做成 checklist 对账"},
|
|
199
|
+
{"seq": 2, "check_id": "data_migration_consumers_checked", "statement_zh": "数据(migration)类消费者已检查", "judgeability": "machine",
|
|
200
|
+
"machine_support": "同上"},
|
|
201
|
+
{"seq": 3, "check_id": "message_consumers_checked", "statement_zh": "消息类消费者已检查", "judgeability": "machine",
|
|
202
|
+
"machine_support": "同上"},
|
|
203
|
+
{"seq": 4, "check_id": "config_consumers_checked", "statement_zh": "配置类消费者已检查", "judgeability": "machine",
|
|
204
|
+
"machine_support": "同上"},
|
|
205
|
+
{"seq": 5, "check_id": "runtime_consumers_checked", "statement_zh": "运行类消费者已检查", "judgeability": "machine",
|
|
206
|
+
"machine_support": "同上"},
|
|
207
|
+
],
|
|
208
|
+
"GATE.BE.API.CONTRACT_CHECKS": [
|
|
209
|
+
{"seq": 1, "check_id": "contract_synced", "statement_zh": "正式契约(OpenAPI)已同步", "judgeability": "machine",
|
|
210
|
+
"machine_support": "operationId 机器键对账(D15)"},
|
|
211
|
+
{"seq": 2, "check_id": "implementation_synced", "statement_zh": "实现已与契约一致", "judgeability": "machine",
|
|
212
|
+
"machine_support": "契约-实现一致性扫描(POLICY.API.CONTRACT_IMPL_CONSISTENCY 为策略正源)"},
|
|
213
|
+
{"seq": 3, "check_id": "generated_client_synced", "statement_zh": "生成客户端已按新契约再生成", "judgeability": "machine",
|
|
214
|
+
"machine_support": "生成产物版本/指纹比对"},
|
|
215
|
+
{"seq": 4, "check_id": "tests_synced", "statement_zh": "兼容测试已更新", "judgeability": "hybrid",
|
|
216
|
+
"machine_support": "测试文件引用 operationId 存在性", "manual_part": "断言语义覆盖度"},
|
|
217
|
+
{"seq": 5, "check_id": "handoff_synced", "statement_zh": "handoff 文档已同步", "judgeability": "hybrid",
|
|
218
|
+
"machine_support": "handoff 产物存在性与引用链", "manual_part": "内容正确性"},
|
|
219
|
+
],
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# ---------------------------------------------------------------- 公共块
|
|
223
|
+
ENFORCEMENT_SEMANTICS = {
|
|
224
|
+
"required_when_applicable": "命中 applies_when 条件时必须遵守;是否升 MUST、接入哪个 gate 由 Human Review 裁决",
|
|
225
|
+
"advisory": "仅建议:任何 gate 永不因本条目单独 FAIL,至多产生 WARN/HINT 或进入 Human Review 议程",
|
|
226
|
+
"deterministic_where_possible": "优先机器判卷;判卷步骤草案见 catalog/gates/ 同协议 recipe",
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def axes_block():
|
|
231
|
+
# PROPOSED ⇒ evidence=PLANNED 与 02 信封跨轴断言自洽
|
|
232
|
+
return {"lifecycle": "PROPOSED", "confidence": "UNRESOLVED", "evidence": "PLANNED", "change": "STABLE"}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ---------------------------------------------------------------- W1-A2 P0.5-1 T3 机器 applicability 标注表
|
|
236
|
+
# PRD v0.5.2 §5.2/§14 + Owner 裁决 8 ②(2026-09-01:lanes 双读过渡 / change_classes 4 值 /
|
|
237
|
+
# 未标注条目=lane 回退行为零变化 O7 / condition 降级 applicability_note)。
|
|
238
|
+
# 保守派生纪律:仅正文词面有明确证据才标;拿不准的留空(lane 回退)+ x-applicability-review
|
|
239
|
+
# 注记 human-review 候选。本表是本工具 60 条命名空间的标注事实源(batch4/curated 各持其表)。
|
|
240
|
+
APPLICABILITY_AXES = {
|
|
241
|
+
# —— capabilities:API 契约面(与 tests/integration/catalog-applicability-case-b.spec.ts
|
|
242
|
+
# W1-A1 批1 fixture 同值同族:policy.api.* + policy.web.api.*)——
|
|
243
|
+
"POLICY.API.BACKWARD_COMPAT_DEFAULTS": {
|
|
244
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
245
|
+
"change_classes": ["API_EVOLUTION"],
|
|
246
|
+
"basis": "condition『接口演进』+ 正文『接口演进默认向后兼容』——API_EVOLUTION 逐字词面",
|
|
247
|
+
},
|
|
248
|
+
"POLICY.API.CONTRACT_IMPL_CONSISTENCY": {
|
|
249
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
250
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
251
|
+
"basis": "condition『任何接口实现或变更』——公共契约面词面",
|
|
252
|
+
},
|
|
253
|
+
"POLICY.API.NO_INFORMAL_CONTRACT": {
|
|
254
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
255
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
256
|
+
"basis": "condition『确定任何接口契约时』——公共契约确立词面",
|
|
257
|
+
},
|
|
258
|
+
"POLICY.WEB.API.DOMAIN_API_ONLY": {
|
|
259
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
260
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注);正文请求层契约消费纪律",
|
|
261
|
+
},
|
|
262
|
+
"POLICY.WEB.API.SINGLE_HTTP_CLIENT": {
|
|
263
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
264
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注);HTTP Client 契约消费面",
|
|
265
|
+
},
|
|
266
|
+
"POLICY.WEB.API.TYPED_DOMAIN_NAMING": {
|
|
267
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
268
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注);请求函数契约类型面",
|
|
269
|
+
},
|
|
270
|
+
"POLICY.WEB.API.QUERY_CANCEL_STALE_DROP": {
|
|
271
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
272
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
273
|
+
},
|
|
274
|
+
"POLICY.WEB.API.MUTATION_IDEMPOTENCY": {
|
|
275
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
276
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
277
|
+
},
|
|
278
|
+
"POLICY.WEB.API.ERROR_NORMALIZATION": {
|
|
279
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
280
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
281
|
+
},
|
|
282
|
+
"POLICY.WEB.API.TRANSPORT_VS_BUSINESS": {
|
|
283
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
284
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
285
|
+
},
|
|
286
|
+
"POLICY.WEB.API.RETRY_DISCIPLINE": {
|
|
287
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
288
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
289
|
+
},
|
|
290
|
+
"POLICY.WEB.API.LATE_RESULT_GUARD": {
|
|
291
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
292
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
293
|
+
},
|
|
294
|
+
"POLICY.WEB.API.TRUSTED_ENDPOINT_SOURCE": {
|
|
295
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
296
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
297
|
+
},
|
|
298
|
+
"POLICY.WEB.API.NO_NETWORK_OPTIMISM": {
|
|
299
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
300
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
301
|
+
},
|
|
302
|
+
"POLICY.WEB.API.GENERATED_CLIENT": {
|
|
303
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
304
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注);condition『正式契约已发布』契约面逐字",
|
|
305
|
+
},
|
|
306
|
+
"POLICY.WEB.API.SINGLE_LOADING_SOURCE": {
|
|
307
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
308
|
+
"basis": "policy.web.api 族(case-b W1-A1 同族标注)",
|
|
309
|
+
},
|
|
310
|
+
"POLICY.WEB.API.CLIENT_CHANGE_IMPACT": {
|
|
311
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
312
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
313
|
+
"basis": "condition『HTTP Client/Domain API 公共行为变更』——公共契约变更词面逐字",
|
|
314
|
+
},
|
|
315
|
+
# —— Authority 锚(§90.2 Protected Set)API 族两条:正文词面明确绑定 API 契约域——
|
|
316
|
+
"AUTHORITY.WEB.API.REQUEST_OWNERS": {
|
|
317
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
318
|
+
"basis": "正文『平台 Owner 维护 HTTP Client,领域 Owner 维护 Domain API,契约 Owner 维护"
|
|
319
|
+
"类型来源』(frontend-hard-spec 15-request-api-protocol.md L71 逐字)——请求族/"
|
|
320
|
+
"API 契约域权属锚词面明确(Benchmark A 泄漏实测后补标,2026-09-01;I9② "
|
|
321
|
+
"2026-09-02 修正引文与源文逐字对齐:原『业务 Owner/数据源』为失真转述)",
|
|
322
|
+
},
|
|
323
|
+
"AUTHORITY.BE.API_CONTRACT_OWNERSHIP": {
|
|
324
|
+
"capabilities": ["CAPABILITY.API_CONTRACT"],
|
|
325
|
+
"basis": "正文『Backend 维护服务端契约,消费者确认联调与兼容结果』(backend-hard-spec "
|
|
326
|
+
"12-api-contract-protocol.md L53 逐字)——后端 API 契约域权属锚(同族补标;"
|
|
327
|
+
"I9② 2026-09-02 修正:原引『API 契约所有权』词形在源文零命中,改引真实逐字句)",
|
|
328
|
+
},
|
|
329
|
+
# —— change_classes:公共契约/依赖/呈现面变更动词面(保守逐例归类)——
|
|
330
|
+
"POLICY.CHG.PRECHANGE_CONSUMER_SCAN": {
|
|
331
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
332
|
+
"basis": "condition 逐字『变更触及公共契约(公共组件/公共API/样式/状态/schema/平台能力)』",
|
|
333
|
+
},
|
|
334
|
+
"POLICY.CHG.COMPAT_MIGRATION_ROLLBACK": {
|
|
335
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
336
|
+
"basis": "condition『公共能力发生不兼容变更时』",
|
|
337
|
+
},
|
|
338
|
+
"POLICY.CHG.BREAKING_VERSIONING": {
|
|
339
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
340
|
+
"basis": "condition『破坏性变更或紧急修复』——破坏性公共契约变更词面",
|
|
341
|
+
},
|
|
342
|
+
"POLICY.CHG.DEPRECATE_BEFORE_DELETE": {
|
|
343
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
344
|
+
"basis": "condition『拟删除任何被依赖能力(props/事件/字段/状态/接口)』——被依赖公共面",
|
|
345
|
+
},
|
|
346
|
+
"POLICY.CHG.OBSERVABLE_EVOLUTION": {
|
|
347
|
+
"change_classes": ["API_EVOLUTION"],
|
|
348
|
+
"basis": "condition『契约演进方式选择』——演进词面逐字(PRD §5.2 示例词形)",
|
|
349
|
+
},
|
|
350
|
+
"POLICY.CHG.STAGED_ROLLOUT": {
|
|
351
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
352
|
+
"basis": "condition『破坏性公共变更』",
|
|
353
|
+
},
|
|
354
|
+
"POLICY.CHG.SYNC_CONTRACT_DOCS_TESTS": {
|
|
355
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
356
|
+
"basis": "condition『任何公共变更落地』",
|
|
357
|
+
},
|
|
358
|
+
"POLICY.CHG.AFFECT_TEMPLATES": {
|
|
359
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
360
|
+
"basis": "condition『公共变更评估』",
|
|
361
|
+
},
|
|
362
|
+
"KNOWLEDGE.CHG.EXAMPLE_PROP_MIGRATION": {
|
|
363
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
364
|
+
"basis": "condition『组件 props 演进』——props 组件公共契约面",
|
|
365
|
+
},
|
|
366
|
+
"KNOWLEDGE.CHG.EXAMPLE_COMPAT_WINDOW": {
|
|
367
|
+
"change_classes": ["API_EVOLUTION"],
|
|
368
|
+
"basis": "condition『字段级契约演进』",
|
|
369
|
+
},
|
|
370
|
+
"KNOWLEDGE.FP.API.FIELD_DRIFT_NO_CONTRACT": {
|
|
371
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
372
|
+
"basis": "condition『接口字段变更』",
|
|
373
|
+
},
|
|
374
|
+
"KNOWLEDGE.FP.BE.CONTRACT_DRIFT": {
|
|
375
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
376
|
+
"basis": "正文『只改实现不同步契约』——契约失同步词面",
|
|
377
|
+
},
|
|
378
|
+
"KNOWLEDGE.FP.CHG.PAGE_LOCAL_PADDING": {
|
|
379
|
+
"change_classes": ["PRESENTATION_CHANGE"],
|
|
380
|
+
"basis": "condition『公共样式/默认值类变更』——呈现面变更逐字",
|
|
381
|
+
},
|
|
382
|
+
"KNOWLEDGE.FP.GRID.GLOBAL_TD_WIDTH": {
|
|
383
|
+
"change_classes": ["PRESENTATION_CHANGE"],
|
|
384
|
+
"basis": "condition『表格样式变更』",
|
|
385
|
+
},
|
|
386
|
+
"GATE.CHG.PRECHANGE_CHECKS": {
|
|
387
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
388
|
+
"basis": "condition『公共变更过门禁』",
|
|
389
|
+
},
|
|
390
|
+
"GATE.BE.API.CONTRACT_CHECKS": {
|
|
391
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
392
|
+
"basis": "condition『接口变更过门禁』",
|
|
393
|
+
},
|
|
394
|
+
"GATE.BE.CHG.CONTRACT_CHANGE_CHECKS": {
|
|
395
|
+
"change_classes": ["PUBLIC_CONTRACT_CHANGE"],
|
|
396
|
+
"basis": "condition『契约变更过门禁』——词面逐字",
|
|
397
|
+
},
|
|
398
|
+
"GATE.WEB.GRID.CHECKS": {
|
|
399
|
+
"change_classes": ["PRESENTATION_CHANGE"],
|
|
400
|
+
"basis": "condition『表格相关变更过门禁』——呈现面变更",
|
|
401
|
+
},
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
APPLICABILITY_CAMPAIGN = "W1-A2 P0.5-1 T3 标注战役(PRD v0.5.2 §5.2/§14;Owner 裁决 8 ②,2026-09-01)"
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def applicability_parts(c):
|
|
408
|
+
"""条目的机器 applicability 组装(lanes 平移 / 词面派生轴 / applicability_note 降级位 / review 注记)。
|
|
409
|
+
|
|
410
|
+
- lanes:显式 lane 平移为 lanes:[同值](裁决 8 ② 双读过渡);lane=any 不标 lanes
|
|
411
|
+
(走缺省回退,O7 行为零变化);
|
|
412
|
+
- capabilities/change_classes:仅 APPLICABILITY_AXES 有明确词面证据的条目;
|
|
413
|
+
- applicability_note:condition 原文降级保留(PRD §5.2 允许自然语言保留为注记,
|
|
414
|
+
不得作为唯一机器路由条件;kernel 契约要求 condition 字段仍在场);
|
|
415
|
+
- x-applicability-review:有机器轴 → annotated + basis;无机器轴 → human_review_candidate
|
|
416
|
+
(拿不准的留空回退 + 条目注记,Human Review 议程)。
|
|
417
|
+
"""
|
|
418
|
+
aw = c["applies_when"]
|
|
419
|
+
merged = dict(aw)
|
|
420
|
+
axes_written = []
|
|
421
|
+
if aw.get("lane") != "any":
|
|
422
|
+
merged["lanes"] = [aw["lane"]]
|
|
423
|
+
axes_written.append("lanes")
|
|
424
|
+
axes = APPLICABILITY_AXES.get(c["candidate_id"])
|
|
425
|
+
basis = None
|
|
426
|
+
if axes is not None:
|
|
427
|
+
basis = axes["basis"]
|
|
428
|
+
for key in ("capabilities", "change_classes"):
|
|
429
|
+
if key in axes:
|
|
430
|
+
merged[key] = list(axes[key])
|
|
431
|
+
axes_written.append(key)
|
|
432
|
+
merged["applicability_note"] = aw["condition"]
|
|
433
|
+
axes_written.append("applicability_note")
|
|
434
|
+
if basis is not None:
|
|
435
|
+
review = {
|
|
436
|
+
"status": "annotated",
|
|
437
|
+
"campaign": APPLICABILITY_CAMPAIGN,
|
|
438
|
+
"axes": axes_written,
|
|
439
|
+
"basis": basis,
|
|
440
|
+
}
|
|
441
|
+
else:
|
|
442
|
+
review = {
|
|
443
|
+
"status": "human_review_candidate",
|
|
444
|
+
"campaign": APPLICABILITY_CAMPAIGN,
|
|
445
|
+
"axes": axes_written,
|
|
446
|
+
"note": "T3 保守派生未见明确词面证据——capabilities/change_classes 留空回退 lane 缺省"
|
|
447
|
+
"(O7 行为零变化);列 Human Review 复核议程",
|
|
448
|
+
}
|
|
449
|
+
return merged, review
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
def authority_block():
|
|
453
|
+
return {
|
|
454
|
+
"owner": "HUMAN_OWNER",
|
|
455
|
+
"delegates": [],
|
|
456
|
+
"write_policy": "EVOLUTION_CHANNEL",
|
|
457
|
+
"escalation_hint": "catalog-pilot-human-review",
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def x_pilot(c, extra=None):
|
|
462
|
+
blk = {
|
|
463
|
+
"status": "PROPOSAL",
|
|
464
|
+
"package": "语义分解试点送审包(" + PILOT_DATE + ")",
|
|
465
|
+
"human_review_required": True,
|
|
466
|
+
"source_type": "design_seed",
|
|
467
|
+
"evidence": "PLANNED",
|
|
468
|
+
"provenance": "POMaster_VNext/catalog/candidates/candidates-draft.json",
|
|
469
|
+
"enforcement_note": ENFORCEMENT_SEMANTICS[c["enforcement"]],
|
|
470
|
+
"clean_room_note": "statement_zh 为独立改写(clean-room),零逐字拷贝源协议",
|
|
471
|
+
}
|
|
472
|
+
if extra:
|
|
473
|
+
blk.update(extra)
|
|
474
|
+
return blk
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def sources_of(c):
|
|
478
|
+
return [{
|
|
479
|
+
"type": "design_seed",
|
|
480
|
+
"ref": c["source_protocol"],
|
|
481
|
+
"captured_by": CAPTURED_BY,
|
|
482
|
+
"locator": {"section": c["source_section"]},
|
|
483
|
+
}]
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
def keywords_of(c):
|
|
487
|
+
return [s.strip() for s in (c.get("statement_en_keywords") or "").split(",") if s.strip()]
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def review_notes_of(c):
|
|
491
|
+
n = (c.get("notes") or "").strip()
|
|
492
|
+
return [n] if n else []
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def review_block_of(c):
|
|
496
|
+
"""pilot-0001 Human Review 处置(disposition/seq/ref [+absorbed_duplicates])。
|
|
497
|
+
|
|
498
|
+
REJECT 条目在物化循环即被 fail-closed 跳过,永不进入本函数;缺 review 字段即 KeyError(fail-closed)。
|
|
499
|
+
"""
|
|
500
|
+
rv = c["review"]
|
|
501
|
+
blk = {"disposition": rv["disposition"], "seq": rv["seq"], "ref": rv["ref"]}
|
|
502
|
+
if "absorbed_duplicates" in rv:
|
|
503
|
+
blk["absorbed_duplicates"] = list(rv["absorbed_duplicates"])
|
|
504
|
+
return blk
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def title_of(c):
|
|
508
|
+
t = TITLES.get(c["candidate_id"])
|
|
509
|
+
if not t:
|
|
510
|
+
raise SystemExit("缺少标题映射: " + c["candidate_id"])
|
|
511
|
+
return t
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
# ---------------------------------------------------------------- 构建器
|
|
515
|
+
def build_policy(c):
|
|
516
|
+
applies_when, review = applicability_parts(c)
|
|
517
|
+
return {
|
|
518
|
+
"x-vocab-pr": {
|
|
519
|
+
"status": "vocab_pr_candidate",
|
|
520
|
+
"finding": "kind='policy' 不在 vocab-lock kinds_registry.truth_bodies(POLICY. 前缀已冻结注册,closed-world)",
|
|
521
|
+
"proposal": "词汇表 PR 登记 policy kind;或 Owner 裁决 policy 条目住 catalog/ 而非 truth/objects 正文层(两种落法待裁决,见 candidates-draft.json meta.vocab_findings[0],affected=45)",
|
|
522
|
+
"locked_vocab_untouched": True,
|
|
523
|
+
},
|
|
524
|
+
"x-pilot-proposal": x_pilot(c),
|
|
525
|
+
"x-applicability-review": review,
|
|
526
|
+
"id": c["candidate_id"],
|
|
527
|
+
"kind": "policy",
|
|
528
|
+
"axis_profile": "policy_default",
|
|
529
|
+
"classification": c["classification"],
|
|
530
|
+
"axes": axes_block(),
|
|
531
|
+
"title_zh": title_of(c),
|
|
532
|
+
"statement_zh": c["statement_zh"],
|
|
533
|
+
"statement_en_keywords": keywords_of(c),
|
|
534
|
+
"applies_when": applies_when,
|
|
535
|
+
"enforcement": c["enforcement"],
|
|
536
|
+
"authority": authority_block(),
|
|
537
|
+
"origin": "ingested",
|
|
538
|
+
"sources": sources_of(c),
|
|
539
|
+
"review_notes": review_notes_of(c),
|
|
540
|
+
"review": review_block_of(c),
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
def build_knowledge(c):
|
|
545
|
+
applies_when, review = applicability_parts(c)
|
|
546
|
+
return {
|
|
547
|
+
"x-vocab-pr": {
|
|
548
|
+
"status": "no_new_enum__confirm_only",
|
|
549
|
+
"finding": "knowledge_entry kind 已在 vocab-lock kinds_registry.truth_bodies——试点纪律所称『knowledge 无正式 kind』与 vocab-lock 实况不符",
|
|
550
|
+
"proposal": "无需新 kind;payload 变体(KNOWLEDGE_PATTERN/FAILURE_PATTERN)作为 knowledge_entry 的 kind profile 承载,提请词汇表 PR 时一并确认,不新增枚举值(meta.vocab_findings[2])",
|
|
551
|
+
"locked_vocab_untouched": True,
|
|
552
|
+
},
|
|
553
|
+
"x-pilot-proposal": x_pilot(c),
|
|
554
|
+
"x-applicability-review": review,
|
|
555
|
+
"x-advisory-gate-semantics": {
|
|
556
|
+
"advisory": True,
|
|
557
|
+
"gate_binding": "NEVER_FAIL",
|
|
558
|
+
"statement": "本条目为 advisory 知识:任何 gate 永不因本条目 FAIL;至多产生 WARN/HINT 或进入 Human Review 议程",
|
|
559
|
+
},
|
|
560
|
+
"id": c["candidate_id"],
|
|
561
|
+
"kind": "knowledge_entry",
|
|
562
|
+
"axis_profile": "knowledge_default",
|
|
563
|
+
"classification": c["classification"],
|
|
564
|
+
"axes": axes_block(),
|
|
565
|
+
"title_zh": title_of(c),
|
|
566
|
+
"statement_zh": c["statement_zh"],
|
|
567
|
+
"statement_en_keywords": keywords_of(c),
|
|
568
|
+
"applies_when": applies_when,
|
|
569
|
+
"enforcement": "advisory",
|
|
570
|
+
"authority": authority_block(),
|
|
571
|
+
"origin": "ingested",
|
|
572
|
+
"sources": sources_of(c),
|
|
573
|
+
"review_notes": review_notes_of(c),
|
|
574
|
+
"review": review_block_of(c),
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def build_gate(c, all_candidates):
|
|
579
|
+
applies_when, review = applicability_parts(c)
|
|
580
|
+
policy_refs = sorted(
|
|
581
|
+
p["candidate_id"] for p in all_candidates
|
|
582
|
+
if p["classification"] in ("UNIVERSAL_POLICY", "LANE_POLICY")
|
|
583
|
+
and p["source_protocol"] == c["source_protocol"]
|
|
584
|
+
)
|
|
585
|
+
anchor = c["candidate_id"] + "@0.1.0"
|
|
586
|
+
return {
|
|
587
|
+
"x-vocab-pr": {
|
|
588
|
+
"status": "vocab_pr_candidate",
|
|
589
|
+
"finding": "GATE. 前缀不在 prefixes_v0 15 前缀闭包内(closed-world:未登记前缀解析即 FATAL);且 kind='gate_recipe' 不在 kinds_registry.truth_bodies",
|
|
590
|
+
"proposal": "词汇表 PR 登记 GATE. 前缀与 gate_recipe kind;备选落法:gate recipe 住 catalog/gates/ 非 truth 对象层,门禁定义锚沿用 03-gate-result.schema gate_def 的 POLICY.GATE.<NAME>@semver 词形(两种落法待 Owner 裁决,meta.vocab_findings[1])",
|
|
591
|
+
"locked_vocab_untouched": True,
|
|
592
|
+
},
|
|
593
|
+
"x-pilot-proposal": x_pilot(c),
|
|
594
|
+
"x-applicability-review": review,
|
|
595
|
+
"id": c["candidate_id"],
|
|
596
|
+
"kind": "gate_recipe",
|
|
597
|
+
"axis_profile": "gate_recipe_default",
|
|
598
|
+
"classification": c["classification"],
|
|
599
|
+
"axes": axes_block(),
|
|
600
|
+
"title_zh": title_of(c),
|
|
601
|
+
"statement_zh": c["statement_zh"],
|
|
602
|
+
"applies_when": applies_when,
|
|
603
|
+
"enforcement": c["enforcement"],
|
|
604
|
+
"gate_def_draft": {
|
|
605
|
+
"anchor": anchor,
|
|
606
|
+
"anchor_note": "03-gate-result.schema gate_def 要求 '<定义id>@semver';若 Owner 裁决 POLICY.GATE.* 落法则改写为 POLICY.GATE." + c["candidate_id"].split(".", 1)[1] + "@0.1.0",
|
|
607
|
+
"result_schema_ref": "POMaster_VNext/packages/schemas/assets/03-gate-result.schema.json",
|
|
608
|
+
"verdict_vocabulary": ["passed", "failed", "warning", "blocked", "not_run", "not_configured", "skipped_blindspot"],
|
|
609
|
+
"judging_rules": {
|
|
610
|
+
"counts_not_applicable_required": "counts.not_applicable 必填——『为何没查』必须是数字而非沉默(C1)",
|
|
611
|
+
"trust_twin": "asserted/recomputed 孪生字段组:永不信任自报值,判卷唯一依据为 GateRunner 重算(C5)",
|
|
612
|
+
"blindspot_evidence": "verdict=skipped_blindspot 必须附 blindspot.fixture_regression 证据引用",
|
|
613
|
+
"aggregate_honesty": "聚合值永远不含未声明的静默跳过;not_configured ≠ passed",
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
"checks": GATE_CHECKS[c["candidate_id"]],
|
|
617
|
+
"policy_refs": policy_refs,
|
|
618
|
+
"authority": authority_block(),
|
|
619
|
+
"origin": "ingested",
|
|
620
|
+
"sources": sources_of(c),
|
|
621
|
+
"review_notes": review_notes_of(c),
|
|
622
|
+
"review": review_block_of(c),
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
|
|
626
|
+
# ---------------------------------------------------------------- 物化
|
|
627
|
+
written = []
|
|
628
|
+
skipped = []
|
|
629
|
+
class_count = {}
|
|
630
|
+
for c in candidates:
|
|
631
|
+
cls = c["classification"]
|
|
632
|
+
class_count[cls] = class_count.get(cls, 0) + 1
|
|
633
|
+
# pilot-0001 fail-closed:Human Review REJECT 条目永不物化(留档 rejected.json,合并指针维持于正本)
|
|
634
|
+
if (c.get("review") or {}).get("disposition") == "REJECT":
|
|
635
|
+
skipped.append({"candidate_id": c["candidate_id"], "classification": cls,
|
|
636
|
+
"reason": "Human Review REJECT(pilot-0001):已归档 catalog/candidates/rejected.json,"
|
|
637
|
+
"duplicate_of=" + (c["review"].get("duplicate_of") or "?")})
|
|
638
|
+
continue
|
|
639
|
+
if cls in ("UNIVERSAL_POLICY", "LANE_POLICY"):
|
|
640
|
+
entry, sub = build_policy(c), "policies"
|
|
641
|
+
elif cls in ("KNOWLEDGE_PATTERN", "FAILURE_PATTERN"):
|
|
642
|
+
entry, sub = build_knowledge(c), "knowledge"
|
|
643
|
+
elif cls == "GATE_RECIPE":
|
|
644
|
+
entry, sub = build_gate(c, candidates), "gates"
|
|
645
|
+
else:
|
|
646
|
+
reason = {
|
|
647
|
+
"DUPLICATE": "让位于合并目标(候选 notes 携带合并指针):pilot-0001 已裁决 REJECT 归档,正本以 review.absorbed_duplicates 维持合并指针",
|
|
648
|
+
"CONTRACT_TEMPLATE": "R-C=b 裁决(pilot-0001):模板暂留 candidates-draft;catalog/templates/ 落点(TEMPLATE. 前缀,V8)挂起至 vocab-pr/GATE 前缀收编后",
|
|
649
|
+
}.get(cls, "未列入本步物化范围")
|
|
650
|
+
skipped.append({"candidate_id": c["candidate_id"], "classification": cls, "reason": reason})
|
|
651
|
+
continue
|
|
652
|
+
|
|
653
|
+
fname = c["candidate_id"].lower() + ".json"
|
|
654
|
+
path = os.path.join(ROOT, sub, fname)
|
|
655
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
656
|
+
data = json.dumps(entry, ensure_ascii=False, indent=2) + "\n"
|
|
657
|
+
with open(path, "w", encoding="utf-8", newline="\n") as f:
|
|
658
|
+
f.write(data)
|
|
659
|
+
written.append({
|
|
660
|
+
"id": c["candidate_id"],
|
|
661
|
+
"path": sub + "/" + fname,
|
|
662
|
+
"content_sha256": "sha256:" + hashlib.sha256(data.encode("utf-8")).hexdigest(),
|
|
663
|
+
"source_ref": c["source_protocol"],
|
|
664
|
+
})
|
|
665
|
+
|
|
666
|
+
written.sort(key=lambda e: e["id"])
|
|
667
|
+
|
|
668
|
+
# ---------------------------------------------------------------- catalog-lock 合并重锁(W1-A2)
|
|
669
|
+
# 旧版直接以本工具 60 条覆写整个 lock——在 batch4(+9)/SPEC-D curated(+25)/W1-E sensors
|
|
670
|
+
# (+6)共推到 100 entries 的现状下重跑会摧毁 lock。W1-A2 T3 标注战役起改为合并重锁
|
|
671
|
+
# (materialize_batch4_uplift.merge_lock 同款语义):本工具命名空间(60 条)整体置换,
|
|
672
|
+
# 基线条目零触碰(id 交叠即 fail-closed),controlled_children 按合并全集重算,
|
|
673
|
+
# 全量 content_sha256 与落盘对账 0 mismatch 才放行(D24:人永不接触哈希)。
|
|
674
|
+
LOCK_PATH = os.path.join(ROOT, "catalog-lock.draft.json")
|
|
675
|
+
# 三个 materialize 工具共用的 producer 链 generated_by(同步落在
|
|
676
|
+
# catalog/tools/materialize_batch4_uplift.py 与 corpus/spec-knowledge/materialize-curated.py;
|
|
677
|
+
# 同串保证任一工具最后落锁不丢失其余批次的 provenance 注记)。
|
|
678
|
+
LOCK_GENERATED_BY = (
|
|
679
|
+
"catalog/tools/materialize_catalog_pilot.py(pilot-0001 60 条;entries 按 id 排序)+ "
|
|
680
|
+
"catalog/tools/materialize_batch4_uplift.py(batch-4 语料批 Universal 上提追加 9 条)+ "
|
|
681
|
+
"corpus/spec-knowledge/materialize-curated.py(SPEC-D 汇总池 D5 精选追加 25 条)+ "
|
|
682
|
+
"catalog/sensors/(P1-5 Sensor Capability Catalog Lite 六条目登记,裁决 8 D6/D7)+ "
|
|
683
|
+
"W1-A2 P0.5-1 T3 标注战役(机器 applicability 字段批量标注 + 幂等重锁;PRD v0.5.2 §5.2/§14,裁决 8 ②)"
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def merge_lock(new_entries):
|
|
688
|
+
with open(LOCK_PATH, encoding="utf-8") as f:
|
|
689
|
+
old_lock = json.load(f)
|
|
690
|
+
own_ids = {e["id"] for e in new_entries}
|
|
691
|
+
assert len(own_ids) == len(new_entries), "本工具条目 id 重复"
|
|
692
|
+
merged = {}
|
|
693
|
+
for e in old_lock["entries"]:
|
|
694
|
+
assert e["id"] not in merged, "旧 lock 重复 id: %s" % e["id"]
|
|
695
|
+
merged[e["id"]] = dict(e)
|
|
696
|
+
for e in new_entries:
|
|
697
|
+
if e["id"] in merged:
|
|
698
|
+
# 幂等重跑:同 id 以本工具产物为准(path 必须一致;sha 以本轮重算为准)。
|
|
699
|
+
assert merged[e["id"]]["path"] == e["path"], "条目 path 漂移: %s" % e["id"]
|
|
700
|
+
merged[e["id"]] = dict(e)
|
|
701
|
+
entries_out = sorted(merged.values(), key=lambda e: e["id"])
|
|
702
|
+
paths = sorted(e["path"] for e in entries_out)
|
|
703
|
+
assert len(paths) == len(set(paths)), "lock path 重复"
|
|
704
|
+
|
|
705
|
+
# 全量对账:lock 每条 content_sha256 与落盘文件 0 mismatch(fail-closed)。
|
|
706
|
+
for e in entries_out:
|
|
707
|
+
with open(os.path.join(ROOT, e["path"].replace("/", os.sep)), "rb") as f:
|
|
708
|
+
actual = "sha256:" + hashlib.sha256(f.read()).hexdigest()
|
|
709
|
+
if actual != e["content_sha256"]:
|
|
710
|
+
raise SystemExit(
|
|
711
|
+
"LOCK_DRIFT: %s(lock=%s disk=%s)——基线条目漂移说明先跑其归属 producer,"
|
|
712
|
+
"或物料被手改;本工具只重锁自己的命名空间" % (e["id"], e["content_sha256"], actual))
|
|
713
|
+
|
|
714
|
+
lock = {
|
|
715
|
+
"catalog_version": old_lock["catalog_version"],
|
|
716
|
+
"profile": old_lock["profile"],
|
|
717
|
+
"generated_by": LOCK_GENERATED_BY,
|
|
718
|
+
"x-digest-ethics": old_lock["x-digest-ethics"],
|
|
719
|
+
"controlled_children": {
|
|
720
|
+
"note": "catalog-lock 管辖面(vocab-lock PR-0001 catalog_layer_vocab 同段语义):"
|
|
721
|
+
"allowed=登记在册可存在;required=必须存在。新增 catalog 文件须同步 allowed+required "
|
|
722
|
+
"两处(batch-4 split-ledger catalog_scope_note 纪律;沿 pomaster directory-lock "
|
|
723
|
+
"controlled_children 语义移植)。",
|
|
724
|
+
"allowed": list(paths),
|
|
725
|
+
"required": list(paths),
|
|
726
|
+
},
|
|
727
|
+
"entries": entries_out,
|
|
728
|
+
"note": old_lock["note"],
|
|
729
|
+
}
|
|
730
|
+
lock_data = json.dumps(lock, ensure_ascii=False, indent=2) + "\n"
|
|
731
|
+
assert lock_data == json.dumps(lock, ensure_ascii=False, indent=2) + "\n", "确定性序列化自检失败"
|
|
732
|
+
with open(LOCK_PATH, "w", encoding="utf-8", newline="\n") as f:
|
|
733
|
+
f.write(lock_data)
|
|
734
|
+
return len(old_lock["entries"]), len(entries_out)
|
|
735
|
+
|
|
736
|
+
# ---------------------------------------------------------------- 统计
|
|
737
|
+
mat_class = {}
|
|
738
|
+
for e in written:
|
|
739
|
+
cid = e["id"]
|
|
740
|
+
c = next(x for x in candidates if x["candidate_id"] == cid)
|
|
741
|
+
mat_class[c["classification"]] = mat_class.get(c["classification"], 0) + 1
|
|
742
|
+
|
|
743
|
+
before_entries, after_entries = merge_lock(written)
|
|
744
|
+
annotated_ids = sorted(APPLICABILITY_AXES)
|
|
745
|
+
materialized_cards = [
|
|
746
|
+
c for c in candidates
|
|
747
|
+
if (c.get("review") or {}).get("disposition") != "REJECT"
|
|
748
|
+
and c["classification"] in ("UNIVERSAL_POLICY", "LANE_POLICY", "KNOWLEDGE_PATTERN",
|
|
749
|
+
"FAILURE_PATTERN", "GATE_RECIPE")
|
|
750
|
+
]
|
|
751
|
+
machine_total = sum(
|
|
752
|
+
1 for c in materialized_cards
|
|
753
|
+
if c["candidate_id"] in APPLICABILITY_AXES or c["applies_when"].get("lane") != "any")
|
|
754
|
+
|
|
755
|
+
stats = {
|
|
756
|
+
"candidates_total": len(candidates),
|
|
757
|
+
"materialized_total": len(written),
|
|
758
|
+
"materialized_by_dir": {
|
|
759
|
+
"policies": sum(1 for e in written if e["path"].startswith("policies/")),
|
|
760
|
+
"knowledge": sum(1 for e in written if e["path"].startswith("knowledge/")),
|
|
761
|
+
"gates": sum(1 for e in written if e["path"].startswith("gates/")),
|
|
762
|
+
},
|
|
763
|
+
"materialized_by_classification": mat_class,
|
|
764
|
+
"w1a2_applicability": {
|
|
765
|
+
"campaign": APPLICABILITY_CAMPAIGN,
|
|
766
|
+
"axes_annotated_ids": annotated_ids,
|
|
767
|
+
"lanes_shifted_any_skip": True,
|
|
768
|
+
"human_review_candidates": sum(
|
|
769
|
+
1 for c in materialized_cards
|
|
770
|
+
if c["candidate_id"] not in APPLICABILITY_AXES and c["applies_when"].get("lane") == "any"),
|
|
771
|
+
"machine_applicability_total": machine_total,
|
|
772
|
+
},
|
|
773
|
+
"lock": {"before_entries": before_entries, "after_entries": after_entries},
|
|
774
|
+
"skipped_total": len(skipped),
|
|
775
|
+
"skipped_by_classification": {
|
|
776
|
+
k: sum(1 for s in skipped if s["classification"] == k) for k in sorted({s["classification"] for s in skipped})
|
|
777
|
+
},
|
|
778
|
+
"lock_entries": after_entries,
|
|
779
|
+
"class_count_all": class_count,
|
|
780
|
+
}
|
|
781
|
+
print(json.dumps(stats, ensure_ascii=False, indent=2))
|
|
782
|
+
print("\n-- skipped --")
|
|
783
|
+
for s in skipped:
|
|
784
|
+
print(s["classification"], s["candidate_id"])
|