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
11 changes: 6 additions & 5 deletions .claude/agents/os-dev.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -284,22 +284,23 @@ dispatch prompt 只携带每单增量(裁决引文、裁决 / PM-机制假设分
issue 对塑造公开契约的某个决定欠规格 —— spec/Zod schema、API 形状、命名、元数据语义 ——
或两种读法通向两种架构时:不猜,不写投机代码。返回 `status: "needs_decision"`,把每个问
题连同选项、成本与你的推荐写进 `open_questions`。
**Analyze every option on three fixed axes — this framing is the core of the escalation,
**Analyze every option on four fixed axes — this framing is the core of the escalation,
not decoration:**

- **Real business need**(实际业务需求)— 该方案服务的是**真实存在的业务场景**,还是投
机性能力面?证据必须**实测** —— 谁在写这个键、谁在读这个能力、示例应用与真实部署怎么
用;「读起来像有用」不作数。**创业阶段聚焦原则**(维护者 2026-08-04:这是创业项目,核
心能力优先):能力扩张默认从紧,无拉动的声明面按 implementation-first 处置,已发布零
消费的能力不因沉没成本获得豁免。这条轴会改变结论,不是陪衬。
用;「读起来像有用」不作数。这条轴会改变结论,不是陪衬。
- **Long-term soundness for THIS project**(项目长远合理性)— 哪个方案符合北极星方向与
可持续架构(no workarounds、contract-first)—— 补丁式选项的长期代价要明说。
- **Making AI-written code — especially AI-authored metadata apps — hard to get wrong**
(防 AI 写代码犯错,尤其是 AI 编写的元数据 app)— 优先选在编写时点就结构性防错的方案
(严格 schema、publish 时响亮拒绝的校验、declared = enforced),而非消费端宽容 —— 宽
容的消费端恰是 AI 生成错误藏身并扩散的地方。
- **Startup scope discipline**(创业阶段不扩散需求)— **创业阶段聚焦原则**(维护者
2026-08-04:这是创业项目,核心能力优先):能力扩张默认从紧,无拉动的声明面按
implementation-first 处置,已发布零消费的能力不因沉没成本获得豁免。

Your recommendation must be justified on all three axes;三轴冲突时如实呈现权衡,交维护
Your recommendation must be justified on all four axes;四轴冲突时如实呈现权衡,交维护
者拍板。同样,`main` 在你脚下碎了、依赖未合并、CI 基础设施故障时,返回 `blocked`(附证
据)—— 先重试到足以确认不是你的改动。

Expand Down
16 changes: 8 additions & 8 deletions .claude/skills/pm-dispatch/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -591,20 +591,20 @@ grep <branch>`),复升级时逐条**跑**一遍,零命中/变形的就地改写
`[Decision] <一句话>` 卡。③ **答复/代裁到手,裁决记录是一个原子动作,四件同笔**(维护者 2026-08-13)
:鲜度门(录前重读晚于正文最后编辑的评论,有修正的先调和正文)/ 状态转换同笔(决策标签或 finding 定
级换结果态,永不留挂)/ `Blocked-by:` 活性现验(合并一半也算解除,耗尽行同笔删)/ 条件已判即判(输入已知的就地判掉);案例与机械两旗见 `references/dispatch-runbook.md`。
**每个方案必须沿三条固定评估轴分析,这是决策分析的核心原则,不是可选项:**
**每个方案必须沿四条固定评估轴分析,这是决策分析的核心原则,不是可选项:**

- **实际业务需求** — 它服务的是**真实存在的业务场景**,还是投机性能力面?判据要求**实测**(谁在
写这个键、谁在读、示例应用与真实部署的用法),「读起来像有用」不作数。**创业阶段聚焦原则**(
维护者 2026-08-04 指示:「我们是一个创业项目,应该先专注于核心能力」):能力扩张默认从紧,无拉
动的声明面按 implementation-first 处置,已发布零消费的能力不因沉没成本获得豁免。这条轴会改
变结论,不是陪衬。
写这个键、谁在读、示例应用与真实部署的用法),「读起来像有用」不作数。这条轴会改变结论,不是陪衬。
- **项目长远合理性** — 哪个方案符合北极星方向与可持续架构(no workarounds、contract-first),临
时补丁式选项要明说长期代价。
- **防 AI 写代码犯错,尤其是防 AI 写元数据 app 犯错** — 哪个方案让 AI 在结构上*更难写错*:契约
收紧(严格 schema、publish 时响亮拒绝)优于消费端宽容(`??` 回退、静默容错)—— 宽容恰是 AI 批
量犯错被掩盖的温床;声明即强制,绝不让 AI 声明一个运行时不兑现的能力。
- **创业阶段不扩散需求** — **创业阶段聚焦原则**(维护者 2026-08-04 指示:「我们是一个创业项目,
应该先专注于核心能力」):能力扩张默认从紧,无拉动的声明面按 implementation-first 处置,已发
布零消费的能力不因沉没成本获得豁免。

推荐意见必须基于这三条轴给出理由;三轴冲突时如实呈现权衡,交维护者拍板。**标准四棱卡面块是落卡与
推荐意见必须基于这四条轴给出理由;四轴冲突时如实呈现权衡,交维护者拍板。**标准四棱卡面块是落卡与
升级的必备件**(四棱维护者 2026-08-11 接受;标准块/摘要视图/批量决裁通道 2026-08-18 裁定「同意」——
块标准化把提取从 LLM 理解题降级成 grep),每张 `needs-user-decision` 卡落卡即带、⛔ 不留待维护者到
场再补。固定形状:首行**机器可寻固定标记** `<!-- os-decision-facets -->`(转义拼写写入,写后回读核
Expand All@@ -614,7 +614,7 @@ defer/remove);③ AI-agent error-resistance(闭合枚举优于自由结构、响
scope discipline(remove 优于 declare-and-maintain,每个已声明的键都是永久义务);一行推荐 + 字母选
项(A/B/…);**一行强制置信缺口(「本分析看不见什么」)** —— 案例(2026-08-15):两张四棱同向、低风
险、全绿、已复核的 PR 仍因分析看不见的方向性前提被整体作废 —— 推荐是输入,永不是放行,人工地板不变。
四棱是三条评估轴的卡面序列化,同一个框架不是第二套;也是分诊代裁置信门的输入(见分诊职责)。交互会
四棱是四条评估轴的卡面序列化,一一对应,同一个框架不是第二套;也是分诊代裁置信门的输入(见分诊职责)。交互会
话可另发 `AskUserQuestion`,带标签的 issue 恒为持久记录。

**摘要视图与批量决裁**(同一 2026-08-18 裁定;实施既有批量裁决 2026-08-15 原话「还是等我批量决裁
Expand DownExpand Up@@ -677,5 +677,5 @@ scope discipline(remove 优于 declare-and-maintain,每个已声明的键都是
| `scripts/pm/dispatch-gates.mjs` | 文件面 → 该跑的门禁族(派发令取数) |
| `scripts/pm/os-regen-merge.sh` | 碰生成物 PR 的 merge 四步序(防静默吞并与锚点倒退) |
| `scripts/pm/ensure-pm-labels.sh` | pm 标签词表的幂等创建 |
| `check:skill-frame-sync` / `-freshness` | 三轴决策框架四份拷贝的同构与新鲜度 |
| `check:skill-frame-sync` / `-freshness` | 四维决策框架四份拷贝的同构与新鲜度 |
| `guard-main-checkout` / `guard-shared-stash` hooks | worktree-first 与 stash 禁令的机械面 |
2 changes: 1 addition & 1 deletion scripts/check-skill-frame-freshness.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -818,7 +818,7 @@ function selfTest() {
label: 'stale tree + authoritative ref → ERROR naming the stale files (the #5866 shape)',
run: () => evaluate({ root: dir, ref: current }),
expect: 'error',
wants: [/STRUCTURALLY BEHIND/, /\.claude\/agents\/os-dev\.md/, /2 axes: long-term-soundness/, /3 axes: business-need/, new RegExp(REMEDY.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))],
wants: [/STRUCTURALLY BEHIND/, /\.claude\/agents\/os-dev\.md/, /3 axes: long-term-soundness/, /4 axes: business-need/, new RegExp(REMEDY.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))],
});
cases.push({
label: 'the SAME stale tree, fetch impossible → degrades to WARN, exit 0, same diagnosis',
Expand Down
35 changes: 23 additions & 12 deletions scripts/check-skill-frame-sync.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -172,6 +172,11 @@ export const AXIS_MAP = [
zh: /防 ?AI ?写(?:代码|元数据)/,
en: /making AI-(?:written|authored) code/i,
},
{
id: 'startup-scope-discipline',
zh: /创业阶段不扩散/,
en: /startup(?:-phase)? scope discipline/i,
},
];

/** Numerals the count sentences are allowed to be written in. */
Expand DownExpand Up@@ -631,22 +636,22 @@ function selfTest() {
' **Long-term soundness for THIS project**',
),
expect: 'red',
wants: [/internal-dev/, /declares 3 axes but 2 axis entries/],
wants: [/internal-dev/, /declares 4 axes but 3 axis entries/],
},
{
// The #5130 shape, coherent: one side becomes a consistent two-axis frame.
label: 'one copy coherently rewritten to two axes → red (cross-copy count)',
// The #5130 shape, coherent: one side becomes a consistent three-axis frame.
label: 'one copy coherently rewritten to three axes → red (cross-copy count)',
copies: () => {
let c = mutate(
base, 'internal-dev',
'- **Long-term soundness for THIS project**',
' **Long-term soundness for THIS project**',
);
c = mutate(c, 'internal-dev', 'on three fixed axes', 'on two fixed axes');
return mutate(c, 'internal-dev', 'on all three axes', 'on all two axes');
c = mutate(c, 'internal-dev', 'on four fixed axes', 'on three fixed axes');
return mutate(c, 'internal-dev', 'on all four axes', 'on all three axes');
},
expect: 'red',
wants: [/do not agree on the NUMBER of axes/, /#5130/, /2 axes {2}internal-dev/],
wants: [/do not agree on the NUMBER of axes/, /#5130/, /3 axes {2}internal-dev/],
},
{
// Regression pin for the draft defect described in soft(): the two-axis form
Expand All@@ -659,8 +664,13 @@ function selfTest() {
'- Making AI-authored code — especially AI-authored metadata — structurally hard',
' Making AI-authored code — especially AI-authored metadata — structurally hard',
);
c = mutate(c, 'published-dev', 'Analyze every option on three fixed axes:', 'Analyze every option on two fixed axes:');
return mutate(c, 'published-dev', 'Justify your recommendation on all three axes', 'Justify your recommendation on both axes');
c = mutate(
c, 'published-dev',
'- Startup scope discipline — do not grow the declared surface',
' Startup scope discipline — do not grow the declared surface',
);
c = mutate(c, 'published-dev', 'Analyze every option on four fixed axes:', 'Analyze every option on two fixed axes:');
return mutate(c, 'published-dev', 'Justify your recommendation on all four axes', 'Justify your recommendation on both axes');
},
expect: 'red',
wants: [/do not agree on the NUMBER of axes/, /2 axes {2}published-dev/],
Expand DownExpand Up@@ -698,7 +708,7 @@ function selfTest() {
label: 'the binding sentence is removed → red (extraction failure, not a skip)',
copies: () => mutate(
base, 'published-pm',
'Your recommendation must be justified on **all three** axes.',
'Your recommendation must be justified on **all four** axes.',
'Your recommendation should be sensible.',
),
expect: 'red',
Expand All@@ -708,7 +718,7 @@ function selfTest() {
label: 'the declaring sentence is removed → red (extraction failure, not a skip)',
copies: () => mutate(
base, 'internal-dev',
'**Analyze every option on three fixed axes',
'**Analyze every option on four fixed axes',
'**Weigh the options sensibly',
),
expect: 'red',
Expand All@@ -718,11 +728,11 @@ function selfTest() {
label: 'a frame count mention drifts from the frame → red',
copies: () => mutate(
base, 'published-pm',
'#### The four-axis decision frame (binding)',
'#### The three-axis decision frame (binding)',
'#### The two-axis decision frame (binding)',
),
expect: 'red',
wants: [/a mention of the frame states 2 axes while the frame itself has 3/],
wants: [/a mention of the frame states 3 axes while the frame itself has 4/],
},
{
label: 'AXIS_MAP misaligned (zh patterns swapped) → red, proving the map is load-bearing',
Expand All@@ -731,6 +741,7 @@ function selfTest() {
{ id: 'business-need', zh: AXIS_MAP[1].zh, en: AXIS_MAP[0].en },
{ id: 'long-term-soundness', zh: AXIS_MAP[0].zh, en: AXIS_MAP[1].en },
AXIS_MAP[2],
AXIS_MAP[3],
],
expect: 'red',
wants: [/do not agree on the axis NAME SEQUENCE/],
Expand Down
53 changes: 29 additions & 24 deletions skills/objectstack-pm-dispatch/SKILL.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -230,7 +230,7 @@ waiting one more round.
- **Maintainer confirm (`needs-user-decision`)** — design cards, feature or
contract-shape proposals, multi-week programs needing appetite and
sequencing, anything touching stored-data migration shape or removing a
shipped capability. The label alone is the inbox entry; the deep three-axis
shipped capability. The label alone is the inbox entry; the deep four-axis
analysis is written when the card is actually taken up.
- **Repair first** — a body truncated by GitHub's sanitizer cannot be
dispatched. Comment the repair instruction and move on.
Expand DownExpand Up@@ -641,14 +641,14 @@ When something *does* pass the bar:
no issue of its own.
3. Write the analysis with: background, the precise question, the options, your
recommendation, and the related issues / PRs / branches — **and analyze
every option on the three fixed axes below.**
every option on the four fixed axes below.**
4. If the session is interactive, additionally ask the maintainer directly; the
labeled issue remains the durable record either way. **Never** answer a
product or architecture question on the maintainer's behalf.

#### The three-axis decision frame (binding)
#### The four-axis decision frame (binding)

Every option in an escalation is analyzed on **all three** axes. This framing is
Every option in an escalation is analyzed on **all four** axes. This framing is
the core of the escalation, not decoration.

**Axis ① — real business need.** Does this option serve a business scenario that
Expand All@@ -657,19 +657,10 @@ the core of the escalation, not decoration.
instead of answering it. The evidence must be **measured, not inferred**: who
writes this key, who reads this capability, how the project's example apps and
real deployments use it today. "It reads like it would be useful" does not
count — and neither does "we already shipped it": a **shipped-but-unconsumed
capability gets no sunk-cost exemption**. A declared surface with no pull is
handled **implementation-first** — narrow the declaration until
`declared = enforced` (retire it, or park the vocabulary and let it return with
the implementation) rather than building implementation to justify a declaration
nobody asked for. **How tight that default should be is your project's call, not
this skill's:** declare the capability-expansion stance in your conventions file —
tight while the core surface is still forming, more permissive once it is
stable — and this axis reads it from there, like every other project-specific
rule. This axis **changes verdicts** rather than decorating them: two findings
count. This axis **changes verdicts** rather than decorating them: two findings
of identical technical shape can be ruled opposite ways on it alone — one
declared surface retired for lack of pull, another kept and made to *reject
loudly* because a real app proved the direction. On the other two axes they
loudly* because a real app proved the direction. On the other three axes they
would read the same, and that would be the wrong answer.

**Axis ② — long-term architectural soundness for *this* project.** Which option
Expand All@@ -688,7 +679,19 @@ reader turns a whole generation of wrong metadata into something that "works"
until it does not. Never let an agent declare a capability the runtime does not
honour.

Your recommendation must be justified on **all three** axes. If they conflict,
**Axis ④ — startup scope discipline.** Do not grow the declared surface while
the core is still forming. "We already shipped it" earns nothing: a
**shipped-but-unconsumed capability gets no sunk-cost exemption**. A declared
surface with no pull is handled **implementation-first** — narrow the
declaration until `declared = enforced` (retire it, or park the vocabulary and
let it return with the implementation) rather than building implementation to
justify a declaration nobody asked for. **How tight that default should be is
your project's call, not this skill's:** declare the capability-expansion
stance in your conventions file — tight while the core surface is still
forming, more permissive once it is stable — and this axis reads it from there,
like every other project-specific rule.

Your recommendation must be justified on **all four** axes. If they conflict,
present the trade-off honestly and let the maintainer decide.

### 9. Round report, then next round
Expand DownExpand Up@@ -798,17 +801,12 @@ or two readings of the issue lead to different architectures: make no guess,
write no speculative code. Return status "needs_decision" with each question,
the options, their costs, and your recommendation in open_questions. A wrong
guess shipped is far more expensive than a round-trip to the maintainer.
Analyze every option on three fixed axes:
Analyze every option on four fixed axes:
- Real business need — does the option serve a business scenario that ACTUALLY
EXISTS, or a speculative capability surface? Ask this first. The evidence must
be MEASURED, not inferred: who writes this key, who reads this capability, how
the project's example apps and real deployments use it today. "It reads like it
would be useful" does not count, and a shipped-but-unconsumed capability gets
no sunk-cost exemption. A declared surface with no pull is handled
implementation-first — narrow the declaration until declared = enforced
(retire it, or park the vocabulary until the implementation arrives) rather
than building implementation to justify the declaration. How tight the default
is comes from the project's conventions file, not from this template.
would be useful" does not count.
- Long-term architectural soundness for THIS project — which option matches a
sustainable architecture (no workarounds, contract-first), not which is
cheapest today. Name the long-term cost of any patch-style option.
Expand All@@ -817,7 +815,14 @@ Analyze every option on three fixed axes:
publish-time validation that rejects loudly, declared = enforced) over
consumer-side tolerance. Lenient consumers are where AI-generated errors hide
and multiply.
Justify your recommendation on all three axes; if they conflict, present the
- Startup scope discipline — do not grow the declared surface: a
shipped-but-unconsumed capability gets no sunk-cost exemption. A declared
surface with no pull is handled implementation-first — narrow the declaration
until declared = enforced (retire it, or park the vocabulary until the
implementation arrives) rather than building implementation to justify the
declaration. How tight the default is comes from the project's conventions
file, not from this template.
Justify your recommendation on all four axes; if they conflict, present the
trade-off and let the maintainer decide.

Return "blocked" (with evidence) when the default branch is broken under you, a
Expand Down
Loading