Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions decisions/ADR-0015-scenario-engine.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ responder.allow 的集合比对)保留 hook(S1-S12 存量);迁移到纯
- `runtime`:运行时执行方式 ∈ {adversary-executed(红队真试), validate-executed(校验器即
执行), manual_only(须带 runtime_note 理由)}

29 条 CT 全部链接完成:10 条 adversary-executed(带场景先决)、3 条 validate-executed、
16 条 manual_only(每条带理由——多数是运行时凭据攻击面,模拟器测不到属诚实边界而非缺陷)。
29 条 CT 全部链接完成:13 条 adversary-executed(带场景先决)、3 条 validate-executed、
13 条 manual_only(每条带理由——多数是运行时凭据攻击面,模拟器测不到属诚实边界而非缺陷)。

validate 双向校验:CT 引用的场景必须存在;scenario.ct_refs 引用的 CT 必须存在;
manual_only 无理由=CI 拒绝。
Expand All @@ -69,7 +69,7 @@ hook 不存在/实现未登记=漂移=FAIL);输出按 class 统计。**新

- 场景可 diff 可 review 可 PR——流程变更破坏可执行性时 CI 精确指出哪条断言红了
- "测试底层方法统一"落地:L1 原语 + L2 声明剧本 + L3 门禁,无第二套方法
- CT 从手册变半机器:声明层先决自动跑,运行时部分显式分类(16 条 manual_only 的理由
- CT 从手册变半机器:声明层先决自动跑,运行时部分显式分类(13 条 manual_only 的理由
本身就是攻击面清单——待自动化时逐条消灭)
- 代价:S1-S12 断言仍在 Python(hook)——声明化不彻底;迁移是增量工作,每迁一个
场景断言数可数(当前声明式 30 条 + hook 12 个)
33 changes: 33 additions & 0 deletions registry/schemas/backlog-entry.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "backlog-entry",
"title": "backlog-entry",
"description": "backlog 条目契约(team-collaboration interfaces.backlog.entry_schema)。maintenance_wave.trigger 引用的 severity/aging 与 producer_gate 延期判定的 defer_condition 以此为字段真源。",
"type": "object",
"required": ["id", "source", "severity", "created_at"],
"properties": {
"id": {"type": "string", "description": "条目唯一标识(issue 编号或 curator 归并号)"},
"source": {"type": "string", "enum": ["drift", "ct", "dependabot", "scorecard", "escape", "amendment", "owner"],
"description": "多写者来源(open 态由扫描器/提案者填;curator 归并时校验)"},
"severity": {"type": "string", "enum": ["security", "high", "normal", "low"],
"description": "triage 时 curator 标注;security 级触发 maintenance_wave 并升 owner_ratify(attention-ledger dep_and_schema_owner_ratify)"},
"created_at": {"type": "string", "format": "date-time",
"description": "入 backlog 时间戳——aging 指标(backlog_aging_p50/p95 与 >30d 触发)的计算基准"},
"evidence": {"type": "string", "description": "指标/证据/期望状态引用(issue 链接或 drift 报告锚点)"},
"expected_state_ref": {"type": "string", "description": "期望状态引用(governance/expected-state.json 锚点,drift 类必填)"},
Comment on lines +16 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Drift reference remains optional 🐞 Bug ≡ Correctness

Entries with source: drift can pass the schema without expected_state_ref, despite both the
schema description and issue lifecycle requiring that reference. Such entries lose the
expected-state anchor needed to triage and repair drift.
Agent Prompt
## Issue description
The schema describes `expected_state_ref` as mandatory for drift entries but never conditionally requires it.

## Issue Context
Add a discriminator condition for `source: drift`, including `required: [source]`, whose `then` requires `expected_state_ref`.

## Fix Focus Areas
- registry/schemas/backlog-entry.json[16-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

"disposition": {"type": "string", "enum": ["open", "consumed", "rejected", "deferred"],
"description": "producer_gate 处置结果;rejected 须附 reason;deferred 须附 defer_condition(无第四态)"},
"reason": {"type": "string", "description": "disposition=rejected 时的驳回理由(必填)"},
"defer_condition": {"type": "string", "description": "disposition=deferred 时的机器可判定条件(必填;到期由 curator 机制扫描重排 top-k)"}
Comment on lines +20 to +21

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Empty disposition metadata accepted 🐞 Bug ≡ Correctness

The schema accepts reason: "" for rejected entries and defer_condition: "" for deferred entries
because both fields are unconstrained strings. These values satisfy required while violating the
lifecycle’s mandatory reason and machine-evaluable deferral condition.
Agent Prompt
## Issue description
Required disposition metadata can currently be empty and still satisfy the schema.

## Issue Context
At minimum, enforce non-empty values with `minLength`; define and validate a structured condition or expression grammar if `defer_condition` must be machine-evaluable.

## Fix Focus Areas
- registry/schemas/backlog-entry.json[18-21]
- registry/schemas/backlog-entry.json[23-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

},
"allOf": [
{
"if": {"properties": {"disposition": {"const": "rejected"}}},
"then": {"required": ["reason"]}
Comment on lines +25 to +26

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Disposition conditions match absence 🐞 Bug ≡ Correctness

Both conditional schemas treat a missing disposition as a match, so an otherwise valid open entry
is incorrectly required to contain both reason and defer_condition. This makes the newly
declared backlog contract reject entries before producer-gate disposition.
Agent Prompt
## Issue description
The `rejected` and `deferred` JSON Schema conditions also match when `disposition` is absent, causing both conditional fields to become required.

## Issue Context
Under JSON Schema semantics, `properties` validates only properties that are present; it does not require `disposition` to exist. Each `if` must explicitly require the discriminator.

## Fix Focus Areas
- registry/schemas/backlog-entry.json[23-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

},
{
"if": {"properties": {"disposition": {"const": "deferred"}}},
"then": {"required": ["defer_condition"]}
}
]
}
4 changes: 3 additions & 1 deletion registry/teams/dev-wave.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ budget:
invariants_ref: standards/team-collaboration.yaml#budget.invariants(升级通道永不冻结)
lifecycle:
type: ephemeral
trigger: intent.received # 组队即 planner 入场产验收示例;intent.ratified=开卡前置(非组队前置)
trigger: intent.received OR maintenance_wave.trigger # 前者:组队即 planner 入场产验收示例,
# intent.ratified=开卡前置(非组队前置);后者:owner 无新意图时
# curator 提请维护波次(flows#maintain_loop——backlog 即波次范围)
archive_to: team:stewardship
handoff: # 执行者见 team-collaboration PART 2 delivery_squad.lifecycle.handoff
- artifacts-pr # team_side: mechanism:git / mechanism:metrics-aggregator / seat:test_author
Expand Down
3 changes: 2 additions & 1 deletion standards/attention-ledger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ asynchronous: # 批量、可延迟、有默认动作
- {item: test_weakening_approval, default_24h: "拒绝(判决树减弱默认冻结——验收范围缩水)",
note: "test-author 特权变更:新卡+owner 批+test_weakening 事件(amendment.classify.test_fix.guard)"}
- {item: dep_and_schema_owner_ratify, default_24h: "PR 保持挂起(默认不批——幻觉依赖/不可逆迁移是真实高频风险)",
note: "change-classes dep/schema 类 review: owner_ratify"}
note: "change-classes dep/schema 类 review: owner_ratify;maintain 回路 security 级条目升级同入此项
(flows#maintain_loop——security 修复多属 dep/schema 面;不新增账本条目,守恒)"}
- {item: sev2_rollback_ack, default_60m: "rollback_safe ? deploy_reverse 预授权 : data_freeze",
note: "incident_cell.authorization.sev2(ack 窗 60m;超时按条件默认——不空等)"}
- {item: flag_enable_decision, default: "不开(flag 默认关=安全侧)",
Expand Down
5 changes: 4 additions & 1 deletion standards/flows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ owner_control:
owner 暂停思考不应烧掉卡的时间预算);usd 已花照记(沉没成本是真实的)
target_states: [building, verify] # 执行态才可暂停;drafting/ratified 本就未走表
event: "card.paused(producer: owner 经平台通道——observability 同模式)"
resume: 回原相位,走表恢复;暂停时长记入卡时间线(trace 可见)
resume: # 顶层动词(与 observability.control_surface.verbs 三动词对齐)
semantics: 回原相位,走表恢复;暂停时长记入卡时间线(trace 可见)
target_states: [paused] # 仅暂停态可恢复——回 pause 进入前的原相位
event: "card.resumed(producer: owner 经平台通道——observability 同模式)"
abort:
semantics: 不可逆终止;reason 必填(落事件——无 reason 的 abort 不可接受:
组织的每个废动作都该有死因,否则 retro 无从归因)
Expand Down
5 changes: 5 additions & 0 deletions standards/scenarios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ scenarios:
- {path: "standards/flows.yaml#maintain_loop.maintenance_wave.trigger", op: contains, value: 30d}
- {path: "standards/flows.yaml#maintain_loop.maintenance_wave.executor", op: contains, value: curator}
- {path: "standards/flows.yaml#maintain_loop.maintenance_wave.acceptance", op: contains, value: pre_approved}
- {path: "standards/team-collaboration.yaml#teams.delivery_squad.lifecycle.trigger", op: contains, value: maintenance_wave.trigger}
- {path: "registry/teams/dev-wave.yaml#lifecycle.trigger", op: contains, value: maintenance_wave.trigger}
- {path: "standards/team-collaboration.yaml#interfaces.backlog.entry_schema", op: exists}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

4. Schema assertion checks only scalar 🐞 Bug ☼ Reliability

The new S15 assertion verifies only that entry_schema contains a non-null scalar, not that the
referenced file exists or parses as JSON Schema. Deleting, misspelling, or corrupting
backlog-entry.json therefore leaves the advertised anti-regression scenario and repository
validator green.
Agent Prompt
## Issue description
The regression assertion checks the reference key but never resolves or validates its target.

## Issue Context
Resolve `interfaces.backlog.entry_schema` within the repository, reject escaping or missing paths, parse the target as JSON, and validate it as a Draft 2020-12 schema. Add negative tests for missing and malformed targets.

## Fix Focus Areas
- standards/scenarios.yaml[131-133]
- scripts/simulate-wave.py[167-185]
- scripts/validate.py[75-85]
- tests/test_validate.py[58-63]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

ct_refs: []
S16-owner-control:
class: regression
Expand All @@ -141,6 +144,8 @@ scenarios:
- {path: "standards/team-collaboration.yaml#flow.event_producers.card.paused", op: exists}
- {path: "standards/team-collaboration.yaml#flow.event_producers.card.aborted", op: exists}
- {path: "standards/observability.yaml#control_surface.verbs", op: contains_all, value: [pause, resume, abort]}
- {path: "standards/flows.yaml#owner_control.verbs", op: contains_all, value: [pause, resume, abort]}
- {path: "standards/flows.yaml#owner_control.verbs.resume.event", op: contains, value: card.resumed}
ct_refs: []
S17-unratified-intent-blocked:
class: control
Expand Down
11 changes: 8 additions & 3 deletions standards/team-collaboration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,12 @@ teams: # 团队原型(team = seats 容器 + scop
assemble_declares: owned_paths [glob...];并发 squad 的 owned_paths 必须不相交,相交 → 拒组建或串行
lifecycle:
type: ephemeral
trigger: intent.received # interface-gateway 结构化后即组队——planner 随队产验收示例;
# intent.ratified 是开卡前置(scheduler 前置检查),非组队前置
# (否则首波次 planner 无所属团队、预算无池可归属)
trigger: intent.received OR maintenance_wave.trigger # 前者:interface-gateway 结构化后即组队
# ——planner 随队产验收示例;intent.ratified 是开卡前置
# (scheduler 前置检查),非组队前置(否则首波次 planner 无
# 所属团队、预算无池可归属);后者:owner 无新意图时 curator
# 提请维护波次(flows#maintain_loop.maintenance_wave——backlog
# 即波次范围,interfaces.backlog.maintenance_trigger)
archive_to: stewardship
handoff: # 销毁前强制交接(每项有执行者——无主清单=队永不销毁)
team_side: # 队侧(destroy 前,相位 handoff)
Expand Down Expand Up @@ -344,6 +347,8 @@ artifacts: # 制品=一切跨阶段/跨团队传递的

interfaces: # 团队间接口(全部 artifact_mediated;读写权限见 channels.acl 唯一真源)
backlog: # 治理→交付的回路(唯一需求入口;读写权限见 channels.acl)
entry_schema: registry/schemas/backlog-entry.json # 条目字段契约(severity/created_at/defer_condition
# ——maintenance_wave.trigger 与 aging 指标的字段真源)
flow: "proposals(多写者)→ curator 单写者归并排序 → merged;adversary 经 findings 由 curator 审核转化(不直写提案)"
producer_gate: planner 组建波次必处置 top-k——每项 纳入/驳回+理由/延期+条件(条件须机器可判定)
maintenance_trigger: owner 无新意图时 curator 提请 maintenance wave(触发条件
Expand Down