@ccoalm/ccl-skills 0.14.0 → 0.15.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.
Files changed (36) hide show
  1. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/SKILL.md +19 -24
  2. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/client-routing.md +32 -32
  3. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/manual-invocation-and-prompts.md +16 -14
  4. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/references/staged-review-contract.md +24 -26
  5. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/AGENTS.md +11 -0
  6. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/claude_review.sh +60 -209
  7. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/init_policy_matrix.py +114 -367
  8. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/parse_probe_result.py +52 -672
  9. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/review_gate.py +10 -2
  10. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/runtime-surface-verification-design.md +4 -2
  11. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_claude_review_probe.sh +77 -444
  12. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_init_policy_matrix.sh +33 -98
  13. package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +57 -173
  14. package/dist/assets/marketplace/plugins/ccl-skills/skills/defect-diagnosis/SKILL.md +1 -1
  15. package/dist/assets/marketplace/plugins/ccl-skills/skills/grill-me/SKILL.md +1 -1
  16. package/dist/assets/marketplace/plugins/ccl-skills/skills/miniapp-product-dev/SKILL.md +1 -1
  17. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-observability/SKILL.md +1 -1
  18. package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/SKILL.md +1 -1
  19. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/SKILL.md +2 -2
  20. package/dist/assets/marketplace/plugins/ccl-skills/skills/product-rd-workflow/references/rd-standards-doc-family-checklist.md +2 -2
  21. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-baseline/SKILL.md +1 -1
  22. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-doc-writer/SKILL.md +1 -1
  23. package/dist/assets/marketplace/plugins/ccl-skills/skills/requirement-scope/SKILL.md +1 -1
  24. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +6 -0
  25. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +1 -1
  26. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +39 -0
  27. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-routing-bank.rb +62 -3
  28. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +114 -10
  29. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/review_ledger_binding.py +36 -13
  30. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +188 -14
  31. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +2 -0
  32. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_eval_routing_bank_resolution.sh +253 -0
  33. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +49 -25
  34. package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_review_ledger_binding.sh +63 -5
  35. package/dist/assets/release.json +41 -36
  36. package/package.json +1 -1
@@ -146,8 +146,8 @@ register_mutation() {
146
146
  # SPECIFIC rejection reason in its stderr.
147
147
  self_check_stderr="$tmp_dir/guard_self_check.err"
148
148
  if mutate_and_expect_mismatch guard-self-check-broken-mutant \
149
- 'def is_bare_host_identifier(identifier: str) -> bool:' \
150
- 'def is_bare_host_identifier(identifier: str) -> bool # deliberately broken' \
149
+ 'def is_authority_name(name: str) -> bool:' \
150
+ 'def is_authority_name(name: str) -> bool # deliberately broken' \
151
151
  >/dev/null 2>"$self_check_stderr"
152
152
  then
153
153
  printf 'the walk accepted a BROKEN mutant as sensitivity; its own guard does not work, so every result below is meaningless\n' >&2
@@ -178,104 +178,39 @@ register_mutation drop-field-name-sanitizer \
178
178
  ' text = name if isinstance(name, str) else repr(name)' \
179
179
  ' return name if isinstance(name, str) else repr(name)'
180
180
 
181
- # The two directions of the host-vocabulary class. Both must be detectable, and
182
- # they fail for opposite reasons: widening it launders a proven customization
183
- # into the cascadable class, while removing it restores the total-outage
184
- # behaviour this class exists to prevent.
185
- register_mutation widen-host-vocabulary-to-any-entry \
186
- ' return bool(BARE_HOST_IDENTIFIER.fullmatch(identifier))' \
187
- ' return True'
181
+ # The MCP list is the one customization surface still required to be empty;
182
+ # dropping that requirement must flip every declared-mcp row.
183
+ register_mutation drop-mcp-empty-requirement \
184
+ 'REQUIRED_EMPTY_INIT_FIELDS = (
185
+ "mcp_servers",
186
+ )' \
187
+ 'REQUIRED_EMPTY_INIT_FIELDS = ()'
188
188
 
189
- register_mutation terminalize-host-vocabulary \
190
- ' return bool(BARE_HOST_IDENTIFIER.fullmatch(identifier))' \
191
- ' return False'
192
-
193
- # Dynamic host command vocabulary is useful only if both halves are enforced:
194
- # the baseline must affect the allow decision, and its CLI version must bind the
195
- # formal init. Baseline skills are deliberately not authority because a leaked
196
- # user skill would otherwise become callable in the formal run.
197
- register_mutation drop-host-baseline-vocabulary \
198
- ' if customization_entry_allowed(
199
- field,
200
- entry,
201
- expected_native_skills,
202
- baseline_commands,
203
- baseline_skills,
204
- ):' \
205
- ' if customization_entry_allowed(
206
- field,
207
- entry,
208
- expected_native_skills,
209
- set(),
210
- set(),
211
- ):'
212
-
213
- register_mutation authorize-host-baseline-skill \
214
- ' identifier in KNOWN_SAFE_BUILTIN_SKILLS
215
- or identifier in selected_names' \
216
- ' identifier in KNOWN_SAFE_BUILTIN_SKILLS
217
- or identifier in baseline_skills
218
- or identifier in selected_names'
219
-
220
- register_mutation drop-host-baseline-required-empty-check \
221
- ' if field not in HOST_VOCABULARY_FIELDS and init_event.get(field) != []:' \
222
- ' if field not in HOST_VOCABULARY_FIELDS and False:'
223
-
224
- register_mutation widen-host-baseline-to-namespaced-entries \
225
- ' or any(
226
- identifier not in known_host_identifiers
227
- and not is_bare_host_identifier(identifier)
228
- for identifier in identifiers
229
- )' \
230
- ' or any(identifier == "<unidentified>" for identifier in identifiers)'
231
-
232
- register_mutation drop-host-baseline-version-binding \
233
- ' if baseline_version is not None and ev.get("claude_code_version") != baseline_version:
234
- # The two invocations no longer prove one same-version host
235
- # vocabulary snapshot. Refuse this lane, but treat the mismatch as
236
- # capability drift rather than a proven tool/authority breach so a
237
- # different reviewer may continue.
238
- unknown_fields.add("claude_code_version:host-baseline-mismatch")' \
239
- ' if False:
240
- unknown_fields.add("claude_code_version:host-baseline-mismatch")'
189
+ # Vocabulary must stay data. Reading a populated skill/command/plugin list as a
190
+ # breach is exactly the outage class policy G removed -- a new host built-in or
191
+ # an installed plugin took the reviewer lane down while proving nothing -- so
192
+ # the oracle must see the class come back.
193
+ register_mutation judge-vocabulary-as-capability \
194
+ ' elif field in KNOWN_VOCABULARY_INIT_FIELDS:
195
+ # Vocabulary, not capability: any value, any shape. Whatever a
196
+ # CLI release or an installed plugin lists here cannot be
197
+ # invoked past the pinned `tools` set.
198
+ continue' \
199
+ ' elif field in KNOWN_VOCABULARY_INIT_FIELDS:
200
+ if isinstance(value, (list, dict)) and value:
201
+ nonempty.add(field)'
241
202
 
242
- # The shape gate. Dropping it lets a structured entry be judged on its `name`
243
- # alone, which reaches TOLERATED when that name is an allowed built-in -- the
244
- # most severe class in this file, so it needs its own mutant rather than riding
245
- # on the bare-identifier one.
246
- register_mutation drop-whole-value-gate \
247
- ' if field in HOST_VOCABULARY_FIELDS and (
248
- not host_entry_is_whole(entry, identifier)
249
- ):' \
250
- ' if False:'
251
-
252
- # ...and the weaker version of the same gate: checking only the SHAPE (a plain
253
- # string) while still judging a truncated token. This is what the gate looked
254
- # like before the third finding, so it must be detectable on its own.
255
- register_mutation weaken-whole-value-gate-to-shape-only \
256
- ' normalized = entry.lower()
257
- if normalized.startswith("/"):
258
- normalized = normalized[1:]
259
- return normalized == identifier' \
260
- ' return True'
261
-
262
- # The regression a round-9 review found in the gate itself: stripping before the
263
- # comparison re-introduces the lossiness the gate exists to reject, and wrapping
264
- # an ALLOWLISTED name in whitespace then reaches TOLERATED.
265
- register_mutation strip-before-the-whole-value-comparison \
266
- ' normalized = entry.lower()' \
267
- ' normalized = entry.strip().lower()'
268
-
269
- register_mutation drop-host-vocabulary-breach-guard \
270
- ' if unclassifiable_vocabulary and not surface_breached:' \
271
- ' if unclassifiable_vocabulary:'
272
-
273
- # The two parse paths implement the class separately, so each needs its own
274
- # mutant: dropping it from the main-invocation predicate leaves the probe path
275
- # correct, which is exactly the shape of divergence this oracle exists to catch.
276
- register_mutation drop-host-vocabulary-from-main-path \
277
- 'runtime_drift_only = bool(unknown or unverifiable or vocabulary) and not (' \
278
- 'runtime_drift_only = bool(unknown or unverifiable) and not ('
203
+ # ...and the softer misreading: vocabulary as schema drift. Same outage, one
204
+ # client switch cheaper, still wrong.
205
+ register_mutation drift-on-vocabulary \
206
+ ' elif field in KNOWN_VOCABULARY_INIT_FIELDS:
207
+ # Vocabulary, not capability: any value, any shape. Whatever a
208
+ # CLI release or an installed plugin lists here cannot be
209
+ # invoked past the pinned `tools` set.
210
+ continue' \
211
+ ' elif field in KNOWN_VOCABULARY_INIT_FIELDS:
212
+ if isinstance(value, (list, dict)) and value:
213
+ unknown_fields.add(field)'
279
214
 
280
215
  # Dispatch the registered walk with bounded concurrency. The mutants are
281
216
  # independent by construction: each writes its own `mutant_<name>.py` copy under
@@ -111,37 +111,9 @@ run_ok_runtime_surface() {
111
111
  --require-empty-init --expected-tools "$expected_tools" --allow-expected-tool-use --runtime-surface-only >/dev/null
112
112
  }
113
113
 
114
- run_ok_expected_native_skills() {
115
- local expected_native_skills="$1" required_native_skills="$2" rc="$3" stdout="$4"
116
- local stderr="${5:-}"
117
- printf '%s' "$stdout" > "$tmp_dir/stdout"
118
- printf '%s' "$stderr" > "$tmp_dir/stderr"
119
- python3 "$parser" "$rc" "$tmp_dir/stdout" "$tmp_dir/stderr" \
120
- --require-empty-init \
121
- --expected-native-skills "$expected_native_skills" \
122
- --required-native-skills "$required_native_skills" >/dev/null
123
- }
124
-
125
- run_reason_expected_native_skills() {
126
- local expected_native_skills="$1" required_native_skills="$2" rc="$3" stdout="$4"
127
- local expected="$5" stderr="${6:-}" out
128
- printf '%s' "$stdout" > "$tmp_dir/stdout"
129
- printf '%s' "$stderr" > "$tmp_dir/stderr"
130
- if out="$(python3 "$parser" "$rc" "$tmp_dir/stdout" "$tmp_dir/stderr" \
131
- --require-empty-init \
132
- --expected-native-skills "$expected_native_skills" \
133
- --required-native-skills "$required_native_skills")"; then
134
- printf 'expected native-skill probe parser failure\n' >&2
135
- return 1
136
- fi
137
- printf '%s' "$out" | grep -F "$expected" >/dev/null
138
- }
139
-
140
- # Runtime-surface variants used to pin the main-invocation drift guard. The
141
- # first omits --allow-expected-tool-use (the wrapper always passes it, so this
142
- # is the guard's defence-in-depth leg); the second exercises the owner-aware
143
- # path, where a permitted-looking customization list can still carry an
144
- # unexpected identifier.
114
+ # Runtime-surface variant used to pin the main-invocation drift guard: it
115
+ # omits --allow-expected-tool-use (the wrapper always passes it, so this is the
116
+ # guard's defence-in-depth leg).
145
117
  run_reason_runtime_surface_no_tool_use_allowance() {
146
118
  local expected_tools="$1" rc="$2" stdout="$3" expected="$4" stderr="${5:-}" out
147
119
  printf '%s' "$stdout" > "$tmp_dir/stdout"
@@ -158,24 +130,6 @@ run_reason_runtime_surface_no_tool_use_allowance() {
158
130
  printf '%s' "$out" | grep -F "$expected" >/dev/null
159
131
  }
160
132
 
161
- run_reason_runtime_surface_native() {
162
- local expected_native_skills="$1" rc="$2" stdout="$3" expected="$4" stderr="${5:-}" out
163
- printf '%s' "$stdout" > "$tmp_dir/stdout"
164
- printf '%s' "$stderr" > "$tmp_dir/stderr"
165
- if out="$(python3 "$parser" "$rc" "$tmp_dir/stdout" "$tmp_dir/stderr" \
166
- --require-empty-init --expected-tools "" --allow-expected-tool-use --runtime-surface-only \
167
- --expected-native-skills "$expected_native_skills" \
168
- --required-native-skills "$expected_native_skills")"; then
169
- printf 'expected owner-aware runtime-surface parser failure\n' >&2
170
- return 1
171
- fi
172
- if printf '%s' "$out" | grep -F 'unrecognized surface-shaped init field' >/dev/null; then
173
- printf 'drift reason must not launder an unexpected identifier: %s\n' "$out" >&2
174
- return 1
175
- fi
176
- printf '%s' "$out" | grep -F "$expected" >/dev/null
177
- }
178
-
179
133
  run_reason_runtime_surface_implicit_strict() {
180
134
  local stdout="$1" expected="$2" out
181
135
  printf '%s' "$stdout" > "$tmp_dir/stdout"
@@ -292,34 +246,25 @@ run_ok_strict 0 "$empty_init"$'\n{"type":"result","subtype":"success","is_error"
292
246
  read_init='{"type":"system","subtype":"init","permissionMode":"default","tools":["Read","Grep","Glob"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[]}'
293
247
  run_ok_expected_tools 'Read,Grep,Glob' 0 "$read_init"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
294
248
  run_ok_expected_tool_use 'Read,Grep,Glob' 0 "$read_init"$'\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Read","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
295
- # Claude Code 2.1.218 exposes these exact host built-ins whenever an explicit
296
- # plugin enables the command registry. They are not plugin-owned commands or
297
- # model tools, so a selected native skill remains valid.
298
- run_ok_expected_native_skills 'testing-strategy' 'testing-strategy' 0 \
299
- $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview"],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
300
- # The same owner-aware path remains value-exact: an arbitrary command cannot
301
- # hide beside the two registered host built-ins.
302
- run_reason_expected_native_skills 'testing-strategy' 'testing-strategy' 0 \
303
- $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview","unrelated:danger"],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
304
- 'runtime capability surface is not empty'
305
- # A dict-shaped entry is never whole, however allowed its `name` reads. The
306
- # entry hides a sibling key the identifier helper discards, so clearing it on
307
- # the truncated name would accept a customization whose proof was in the part
308
- # that was thrown away. host_entry_is_whole must reject the shape BEFORE the
309
- # allowlist reads it; flipping its non-string branch to True makes this case
310
- # pass, which is exactly the regression this asserts.
311
- run_reason_expected_native_skills 'testing-strategy' 'testing-strategy' 0 \
312
- $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec",{"name":"ultrareview","path":"hidden-sibling-value"}],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
313
- 'runtime capability surface is not empty'
314
-
315
- # A matching name in either executable surface is still terminal. Built-in UI
316
- # registration never authorizes a tool declaration or invocation.
317
- run_reason_expected_native_skills 'testing-strategy' 'testing-strategy' 0 \
249
+ # Claude Code 2.1.261 lists its own built-in commands and skills, plus every
250
+ # installed plugin entry, whenever an explicit plugin enables the command
251
+ # registry. They are vocabulary, not model tools: any entry is tolerated on
252
+ # both parse paths, including names the host adds tomorrow, namespaced or
253
+ # structured entries, and the selected owner's own namespaced command.
254
+ vocab_init='{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview","workflow-authoring","unrelated:danger",{"name":"ultrareview","path":"hidden-sibling-value"}],"terminal_slash_commands":["doctor"],"skills":["testing-strategy","workflow-authoring","brand-new-skill"],"plugins":["ccl-skills",{"name":"other","path":"/p"}]}'
255
+ run_ok_strict 0 "$vocab_init"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
256
+ run_ok_runtime_surface '' 0 "$vocab_init"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
257
+ # A matching name in either executable surface is still terminal. Vocabulary
258
+ # never authorizes a tool declaration, a tool invocation, or an MCP server.
259
+ run_reason_strict 0 \
318
260
  $'{"type":"system","subtype":"init","permissionMode":"default","tools":["workflow-launch-exec"],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview"],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
319
261
  'runtime capability surface is not empty'
320
- run_reason_expected_native_skills 'testing-strategy' 'testing-strategy' 0 \
262
+ run_reason_strict 0 \
321
263
  $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview"],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"workflow-launch-exec","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
322
264
  'runtime capability surface is not empty'
265
+ run_reason_strict 0 \
266
+ $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":["inherited"],"slash_commands":["ccl-skills:testing-strategy","workflow-launch-exec","ultrareview"],"skills":["testing-strategy"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' \
267
+ 'runtime capability surface is not empty'
323
268
  run_reason_expected_tools_implicit_strict 'Read,Grep,Glob' 0 'ok' \
324
269
  'missing the required stream-json init evidence'
325
270
  run_reason_runtime_surface '' 0 "$empty_init"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'auth-path false negative' 'Not logged in · Please run /login'
@@ -422,42 +367,31 @@ run_reason_strict 0 $'{"type":"system","subtype":"init","permissionMode":"defaul
422
367
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":["Bash"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"capabilities":["interrupt_cancel_queued_v1"],"fast_mode_disabled_reason":"sdk_opt_in_required"}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'the no-tool sandbox is not enforced'
423
368
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":["Write"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"capabilities":["interrupt_cancel_queued_v1"],"fast_mode_disabled_reason":"sdk_opt_in_required"}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
424
369
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"fast_mode_disabled_reason":"sdk_opt_in_required"}\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Write","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
425
- # Drift + a real breach in the same init must report as the BREACH. Review round
426
- # 4 suspected `unexpected_customization_identifiers` was missing from the
427
- # main-path `runtime_drift_only` guard; it stays out because every identifier it
428
- # reports lands in a set that IS in the guard, and these fixtures pin that so the
429
- # soft drift reason can never launder a combined case. Note which set: an
430
- # identifier that is provably a customization marks its field non-empty, while a
431
- # bare host-vocabulary name lands in the unclassifiable set instead — so the
432
- # fixtures below use a NAMESPACED foreign identifier, which is the one that is
433
- # still a proven breach.
434
- run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["some-skill"],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'runtime isolation surface is invalid'
435
- run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["some-skill"],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'unexpected_customizations=skills'
436
- # ...and the main-path guard must match the probe path's breach set exactly.
437
- # A tool_use with no allowance, and an unexpected identifier under an owner-aware
438
- # run, are the two legs where the two guards could silently diverge again.
370
+ # Drift + a real breach in the same init must report as the BREACH, and these
371
+ # fixtures pin that so the soft drift reason can never launder a combined case.
372
+ # The breach here is an inherited MCP server -- the one customization list that
373
+ # is still a capability surface.
374
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":["some-server"],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'runtime isolation surface is invalid'
375
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":["some-server"],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'unexpected_customizations=mcp_servers'
376
+ # ...and the main-path guard must match the probe path's breach set exactly:
377
+ # a tool_use with no allowance is the leg where the two guards could silently
378
+ # diverge again.
439
379
  run_reason_runtime_surface_no_tool_use_allowance 'Write' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":["Write"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Write","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'runtime isolation surface is invalid'
440
- run_reason_runtime_surface_native 'testing-strategy' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy"],"skills":["testing-strategy","other-plugin:unrelated-skill"],"plugins":["ccl-skills"],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'unexpected_customization_identifiers=skills:other-plugin:unrelated-skill'
441
- # The same fixture with a BARE unknown skill is deliberately the other verdict:
442
- # it reports the soft class, because a bare name outside the built-in snapshot is
443
- # not proof of a customization. Pinned explicitly so the split above is asserted
444
- # rather than merely allowed by the fixture's choice of identifier. `future_surface`
445
- # is dropped here on purpose — with schema drift also present the reason is the
446
- # broader drift phrase, which this helper forbids by design; that combined case is
447
- # pinned in the policy matrix instead.
448
- run_reason_runtime_surface_native 'testing-strategy' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy"],"skills":["testing-strategy","unrelated-skill"],"plugins":["ccl-skills"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'unclassifiable_host_vocabulary=skills:unrelated-skill'
380
+ # Vocabulary beside schema drift is still only drift: the populated lists add
381
+ # nothing to the verdict, so the reason stays the fallback-eligible drift phrase.
382
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["ccl-skills:testing-strategy","brand-new-builtin"],"skills":["testing-strategy","other-plugin:unrelated-skill"],"plugins":["ccl-skills"],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"terminal_reason":"completed","structured_output":{"mode":"challenge","findings":[]}}' 'unrecognized surface-shaped init field'
449
383
  # Same rule on the probe path: drift alongside a declared surface, an unexpected
450
384
  # tool, or a tool_use must report the BREACH. The drift phrase routes to
451
385
  # fallback, so reaching it first would launder a real breach.
452
- combo_drift_breach=$'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["some-skill"],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
386
+ combo_drift_breach=$'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":["some-server"],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
453
387
  run_reason 0 "$combo_drift_breach" 'runtime capability surface is not empty'
454
388
  run_reason_excludes 0 "$combo_drift_breach" 'unrecognized surface-shaped init field'
455
389
  combo_drift_tool=$'{"type":"system","subtype":"init","permissionMode":"default","tools":["Write"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
456
390
  run_reason_excludes 0 "$combo_drift_tool" 'unrecognized surface-shaped init field'
457
391
  combo_drift_use=$'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[],"future_surface":["x"]}\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Write","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
458
392
  run_reason_excludes 0 "$combo_drift_use" 'unrecognized surface-shaped init field'
459
- # A declared CCL skill/plugin surface is still rejected under drift tolerance.
460
- run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["some-skill"],"plugins":[],"fast_mode_disabled_reason":"sdk_opt_in_required"}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
393
+ # An inherited MCP server is still rejected under drift tolerance.
394
+ run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":["some-server"],"slash_commands":[],"skills":[],"plugins":[],"fast_mode_disabled_reason":"sdk_opt_in_required"}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
461
395
  # THE flakiness fix: model hallucinates TOOL_ENABLED but every runtime surface is empty -> pass.
462
396
  run_ok 0 "$empty_init"$'\n{"type":"result","subtype":"success","is_error":false,"num_turns":1,"permission_denials":[],"result":"TOOL_ENABLED"}'
463
397
  # clean ok via stream -> pass.
@@ -470,9 +404,10 @@ run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","too
470
404
  # declared set; unknown/non-string elements make init ground truth invalid.
471
405
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[{"name":"Bash"}],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'missing required isolation fields'
472
406
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[{"name":"x"}],"slash_commands":[],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
473
- run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["review"],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
474
- run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["review"],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
475
- run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":["x"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
407
+ # Skill, command and plugin lists are vocabulary: populated is not a breach.
408
+ run_ok 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["review"],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
409
+ run_ok 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":["review"],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
410
+ run_ok 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":["x"]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
476
411
  # closes the latent false-negative: Bash DECLARED in init.tools, reply says ok -> fail.
477
412
  run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":["Bash","Read"],"mcp_servers":[],"slash_commands":[],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'Bash tool is available'
478
413
  # Bash actually INVOKED via tool_use block -> fail (sandbox not enforced).
@@ -509,76 +444,25 @@ run_reason 0 "$empty_init"$'\n{"type":"system","subtype":"init","permissionMode"
509
444
  # pretty-printed single envelope (bare-brace lines) must still pass via the text fallback.
510
445
  run_ok 0 $'{\n "type": "result",\n "subtype": "success",\n "is_error": false,\n "result": "ok"\n}'
511
446
 
512
- # --- host vocabulary is unverifiable, not a proven breach -------------------
513
- # The review-skill invocation is the only shape whose customization lists are
514
- # populated by the host's own built-ins, so a name this repo's snapshot does not
515
- # know cannot be shown to be a user customization. It must refuse WITHOUT
516
- # terminating the lane; anything that IS provably a customization must not
517
- # inherit that softer class. `product-rd-workflow` is used as the selected skill
518
- # because a name that is also a built-in skill trips the ambiguous-owner guard
519
- # and would mask the verdict under test.
520
- native_vocab_result=$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
521
- native_vocab_init() {
522
- printf '{"type":"system","subtype":"init","permissionMode":"default","tools":%s,"mcp_servers":[],"slash_commands":%s,"skills":%s,"plugins":[{"name":"ccl-skills"}]}' \
523
- "${1:-[]}" "${2:-[\"init\",\"agents\"]}" "${3:-[\"ccl-skills:product-rd-workflow\",\"dataviz\"]}"
524
- }
525
- run_reason_native_excludes() {
526
- local stdout="$1" forbidden="$2" expected="$3" out
527
- printf '%s' "$stdout" > "$tmp_dir/stdout"
528
- : > "$tmp_dir/stderr"
529
- if out="$(python3 "$parser" 0 "$tmp_dir/stdout" "$tmp_dir/stderr" \
530
- --require-empty-init \
531
- --expected-native-skills product-rd-workflow \
532
- --required-native-skills product-rd-workflow)"; then
533
- printf 'expected native-skill parser failure for stdout: %s\n' "$stdout" >&2
534
- return 1
535
- fi
536
- if printf '%s' "$out" | grep -F "$forbidden" >/dev/null; then
537
- printf 'a proven customization must not report as %q: %s\n' "$forbidden" "$out" >&2
538
- return 1
539
- fi
540
- printf '%s' "$out" | grep -F "$expected" >/dev/null
541
- }
542
- # the base itself is accepted, or none of the rows below prove anything
543
- run_ok_expected_native_skills product-rd-workflow product-rd-workflow 0 \
544
- "$(native_vocab_init)$native_vocab_result"
545
- # a built-in the snapshot has not caught up with, in either host-vocabulary field
546
- run_reason_expected_native_skills product-rd-workflow product-rd-workflow 0 \
547
- "$(native_vocab_init '[]' '["init","agents","brand-new-builtin"]')$native_vocab_result" \
548
- 'unclassifiable host-vocabulary entry'
549
- run_reason_expected_native_skills product-rd-workflow product-rd-workflow 0 \
550
- "$(native_vocab_init '[]' '["init"]' '["ccl-skills:product-rd-workflow","brand-new-skill"]')$native_vocab_result" \
551
- 'unclassifiable host-vocabulary entry'
552
- # ...and the identifier is named, so the follow-up is a one-liner
553
- run_reason_expected_native_skills product-rd-workflow product-rd-workflow 0 \
554
- "$(native_vocab_init '[]' '["init","brand-new-builtin"]')$native_vocab_result" \
555
- 'slash_commands:brand-new-builtin'
556
- # A NAMESPACED entry proves a surface beyond the one expected plugin; a
557
- # path-shaped or unparseable identifier proves nothing about host origin; a
558
- # duplicate is a spoofing signal. All four stay terminal.
559
- run_reason_native_excludes \
560
- "$(native_vocab_init '[]' '["init","evil-plugin:pwn"]')$native_vocab_result" \
561
- 'unclassifiable host-vocabulary' 'runtime capability surface is not empty'
562
- run_reason_native_excludes \
563
- "$(native_vocab_init '[]' '["init","dir/cmd"]')$native_vocab_result" \
564
- 'unclassifiable host-vocabulary' 'runtime capability surface is not empty'
565
- run_reason_native_excludes \
566
- "$(native_vocab_init '[]' '["init","ev!l"]')$native_vocab_result" \
567
- 'unclassifiable host-vocabulary' 'runtime capability surface is not empty'
568
- run_reason_native_excludes \
569
- "$(native_vocab_init '[]' '["init","init"]')$native_vocab_result" \
570
- 'unclassifiable host-vocabulary' 'runtime capability surface is not empty'
571
- # The softer class must never absorb a real breach that happens alongside it.
572
- run_reason_native_excludes \
573
- "$(native_vocab_init '["Write"]' '["init","brand-new-builtin"]')$native_vocab_result" \
574
- 'unclassifiable host-vocabulary' 'runtime capability surface is not empty'
575
- # Same policy on the main-invocation path, with the identifier in the detail
576
- # fields so an operator can see which name drifted.
577
- run_reason_runtime_surface_native product-rd-workflow 0 \
578
- "$(native_vocab_init '[]' '["init","brand-new-builtin"]')$native_vocab_result" \
579
- 'unclassifiable host-vocabulary entry'
580
- run_reason_runtime_surface_native product-rd-workflow 0 \
581
- "$(native_vocab_init '[]' '["init","brand-new-builtin"]')$native_vocab_result" \
582
- 'unclassifiable_host_vocabulary=slash_commands:brand-new-builtin'
447
+ # --- vocabulary is data, not a verdict --------------------------------------
448
+ # Any value in slash_commands / terminal_slash_commands / skills / plugins is
449
+ # tolerated on both parse paths; only tools, tool_use, the MCP list and
450
+ # permissionMode decide. Pinned so the class can never be tightened back into a
451
+ # snapshot of the host's own names: that snapshot made every CLI release that
452
+ # shipped a new built-in a reviewer-lane outage while proving nothing.
453
+ vocab_any='{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["init","brand-new-builtin","evil-plugin:pwn","dir/cmd","ev!l","init"," import","brand-new runtime isolation"],"terminal_slash_commands":[{"name":"init"},"not-declared"],"skills":["brand-new-skill",{"name":"verify","command":"/x/y"},"evil-plugin:pwn"],"plugins":[{"name":"ccl-skills"},{"name":"other","path":"/p"},"x"]}'
454
+ run_ok_strict 0 "$vocab_any"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
455
+ run_ok_runtime_surface '' 0 "$vocab_any"$'\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
456
+ # absent or oddly typed vocabulary fields are not "missing isolation fields"
457
+ run_ok_strict 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
458
+ run_ok_strict 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":{"a":1},"skills":"none","plugins":null,"terminal_slash_commands":"doctor"}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}'
459
+ # ...while the MCP list, the one customization list that is capability, must
460
+ # still be present and empty.
461
+ run_reason_strict 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"slash_commands":[],"skills":[],"plugins":[]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'missing required isolation fields'
462
+ # ...and every breach class keeps its strength beside vocabulary.
463
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":["Write"],"mcp_servers":[],"slash_commands":["init","brand-new-builtin"],"skills":["brand-new-skill"],"plugins":[{"name":"ccl-skills"}]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime isolation surface is invalid'
464
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"bypassPermissions","tools":[],"mcp_servers":[],"slash_commands":["init","brand-new-builtin"],"skills":["brand-new-skill"],"plugins":[{"name":"ccl-skills"}]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'unsafe_values=permissionMode'
465
+ run_reason_runtime_surface '' 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[{"name":"x"}],"slash_commands":["init","brand-new-builtin"],"skills":["brand-new-skill"],"plugins":[{"name":"ccl-skills"}]}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'unexpected_customizations=mcp_servers'
466
+ run_reason 0 $'{"type":"system","subtype":"init","permissionMode":"default","tools":[],"mcp_servers":[],"slash_commands":["init","brand-new-builtin"],"skills":["brand-new-skill"],"plugins":[{"name":"ccl-skills"}]}\n{"type":"assistant","message":{"content":[{"type":"tool_use","name":"Write","input":{}}]}}\n{"type":"result","subtype":"success","is_error":false,"result":"ok"}' 'runtime capability surface is not empty'
583
467
 
584
468
  printf 'parse_probe_result_tests_ok\n'
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: defect-diagnosis
3
- description: bug / 报错 / test 挂了 / 线上问题 / 复现 / 找根因 / debug → diagnose first-hand failure evidence, isolate cause, verify before fixing, add regression proof, and route prevention. Also use for AI-proposed causes or fixes.
3
+ description: bug / 报错 / test 挂了 / 线上问题 / 接口变慢·性能退化 / 复现 / 找根因 / debug → diagnose first-hand failure evidence, isolate cause, verify before fixing, add regression proof, and route prevention. Also use for AI-proposed causes or fixes.
4
4
  ---
5
5
 
6
6
  # Defect Diagnosis
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: grill-me
3
- description: grill-me / 访谈 / 拷问 / 压力测试方案 / stress-test a plan — lightweight one-question-at-a-time interview to challenge a plan, design, API shape, data model, or feature direction before implementation. Skip code-level YAGNI/delete/adversarial review of written code → `product-rd-workflow`'s independent-review gate; full delivery/spec/plan authoring → product-rd-workflow; tests → testing-strategy; implementation → stack/dev skill; process lesson extraction → skill-extraction-workflow.
3
+ description: grill-me / 访谈 / 一问一答拷问(一次问一个)/ 压力测试方案 / stress-test a plan — lightweight one-question-at-a-time interview to challenge a plan, design, API shape, data model, or feature direction before implementation. Skip 拷问用的问题池·推荐默认值等材料,以及拷问后的结论整理(不是逐问过程)→ requirement-intent;code-level YAGNI/delete/adversarial review of written code → `product-rd-workflow`'s independent-review gate; full delivery/spec/plan authoring → product-rd-workflow; tests → testing-strategy; implementation → stack/dev skill; process lesson extraction → skill-extraction-workflow.
4
4
  ---
5
5
 
6
6
  # grill-me — 轻量方案拷问
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: miniapp-product-dev
3
- description: "小程序 / Taro / 微信小程序 / 支付宝小程序 / 抖音小程序 / 小程序上线审核 → implement, debug, test, and ship mini-program client features: pages, state, API integration, auth, sharing, platform capabilities, review, and device verification. Triggers also include \"重构这个小程序页面/组件(局部)\", \"refactor a mini-program page/component\"."
3
+ description: "小程序 / Taro / 微信小程序 / 支付宝小程序 / 抖音小程序 / 小程序上线审核 / 微信开发者工具编译·构建·真机调试 → implement, debug, test, and ship mini-program client features: pages, state, API integration, auth, sharing, platform capabilities, review, and device verification. Triggers also include \"重构这个小程序页面/组件(局部)\", \"refactor a mini-program page/component\"."
4
4
  ---
5
5
 
6
6
  # Miniapp Product Dev
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: platform-observability
3
- description: Use when designing, reviewing, debugging, or shipping observability — service logs, metrics, distributed tracing, log/trace correlation, dashboards, alerts, on-call routing(值班/排班 SOP、P0/P1 打断;发布值班/回滚除外), SLI/SLO, error budgets — for a backend product. Owns the cross-cutting evidence layer — what signals must exist, what fields must propagate, what middleware must auto-wire, what verification proves a change is observable in production. Hand off mesh/routing/mTLS to `platform-service-connectivity`, release gates and rollback evidence to `platform-release-engineering`, service-internal architecture (HTTP/RPC/DB/queue) to `python-service-architecture` / `go-microservice-architecture`. Product-agnostic; do not depend on specific repository names, service names, hostnames, or business domains.
3
+ description: Use when designing, reviewing, debugging, or shipping observability — service logs, metrics, distributed tracing, log/trace correlation, 给接口·服务加结构化日志与 trace 透传, dashboards, alerts, on-call routing(值班/排班 SOP、P0/P1 打断;发布值班/回滚除外), SLI/SLO, error budgets, 线上是否已启用(开关·配置在生产的实际生效状态)— for a backend product. Owns the cross-cutting evidence layer — what signals must exist, what fields must propagate, what middleware must auto-wire, what verification proves a change is observable in production. Hand off mesh/routing/mTLS to `platform-service-connectivity`, release gates and rollback evidence to `platform-release-engineering`, service-internal architecture (HTTP/RPC/DB/queue) to `python-service-architecture` / `go-microservice-architecture`. Product-agnostic.
4
4
  ---
5
5
 
6
6
  # Platform Observability
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: platform-release-engineering
3
- description: 发布 / 灰度 / canary / rollback / rollout / 环境泳道 / promotion gate → design or review how a change moves from build to traffic and back safely, including rollout strategy, approval, rollback, secrets, config, and deploy control planes. Skip when the ask is the production release lifecycle — 上线范围确认 / 合并 main / 打 tag / 生产构建 / 发布后 reset → release-coordination; release document substance → release-doc-writer.
3
+ description: 发布 / 灰度 / canary / rollback / rollout / 环境泳道 / promotion gate / 发布值班 SOP(P0·P1 打断排班、是否回滚)→ design or review how a change moves from build to traffic and back safely, including rollout strategy, approval, rollback, secrets, config, and deploy control planes. Skip when the ask is the production release lifecycle — 上线范围确认 / 合并 main / 打 tag / 生产构建 / 发布后 reset → release-coordination; release document substance → release-doc-writer.
4
4
  ---
5
5
 
6
6
  # Platform Release Engineering
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: product-rd-workflow
3
- description: 加功能 / 新需求 / 技术方案 / 方案评估 / 技术选型 / 可行性评估 / 工作量评估 / 多阶段重构 / 推倒重来 / 重新开发 / 完全重新开始 / 清除代码重新开发 / redo-from-scratch / 项目分析 / spec·PRD·需求文档实质内容写错要改对(substance 修正) / 方案评审通过开始实现 / 进入实现阶段 → end-to-end product R&D router for requirement shaping, spec/plan, implementation gates, assessment, redo/refactor, and multi-stack standards.
3
+ description: 加功能/新需求/技术方案/方案评估/技术选型/可行性评估/工作量评估/多阶段重构/推倒重来/重新开发/完全重新开始/清除代码重新开发/redo-from-scratch/继续之前的重构·开发/resume-in-flight-delivery/项目分析/无架构兄弟栈的服务边界·数据归属/service-boundary-data-ownership/spec·PRD·需求文档实质内容写错要改对(substance 修正)/方案评审通过·进入实现阶段 → end-to-end product R&D router for requirement shaping, spec/plan, implementation gates, assessment, redo/refactor, and multi-stack standards.
4
4
  ---
5
5
 
6
6
  # Product R&D Workflow
@@ -43,7 +43,7 @@ Use this skill as the top-level workflow for new product development, feature de
43
43
  - Skill/process extraction: when asked to summarize delivery experience, preserve a workflow lesson, update a reusable skill, or decide where a lesson belongs, route to `skill-extraction-workflow` first. Update this skill only when the lesson changes product R&D routing, gates, ownership, or lifecycle policy.
44
44
  - Upstream decision propagation: when architecture, design, testing strategy, release, observability, security, or product workflow guidance changes, treat the next R&D slice as incomplete until the downstream execution owners are named. Confirm which implementation skill, test/review skill, and release or docs owner must apply the decision, or route the gap through `skill-extraction-workflow`.
45
45
  - Text artifact quality: when this workflow creates or updates a SOP, template, checklist, report, Feishu/Lark doc, task card, launch material, or other deliverable text, run `tighten-doc` before sharing, syncing, committing, or publishing. Do not ask the user for a separate optimization confirmation unless substantive decisions may change or collaborative-comment safety is at risk.
46
- - Product R&D standards docs: when creating or updating team development standards, stack guidelines, testing standards, engineering norms, or a multi-doc handbook that belongs to the R&D lifecycle, use the R&D standards checklist in Workflow. Cross-stack or cross-service product Specs live in one authority surface; stack/service repositories keep execution slices and links back to that authority instead of redefining product goals. A multi-stack standards family must include a testing standard owned by `testing-strategy`; stack docs specialize commands and harness mechanics but do not replace the shared test-layer and CI-gate policy. For standalone wording, editing, or polishing requests with no R&D routing decision, use `tighten-doc` directly. Authority/sync-gate and testing-standard detail: `references/rd-standards-doc-family-checklist.md`.
46
+ - Product R&D standards docs: when creating or updating team development standards, stack guidelines, testing standards, engineering norms, or a multi-doc handbook that belongs to the R&D lifecycle, you must use the R&D standards checklist in Workflow. For standalone wording, editing, or polishing requests with no R&D routing decision, use `tighten-doc` directly. Authority/sync-gate and testing-standard detail: `references/rd-standards-doc-family-checklist.md`.
47
47
  - Standards-to-health-gate propagation: when a standards family is intended to check project compliance later, split each norm into deterministic checks and agent review checks, route the executable invariant model to `testing-strategy` fitness functions and the stack-specific mechanics to the owning dev/architecture skills, and do not leave conformance as a human-only checklist (mapping detail in `references/rd-standards-doc-family-checklist.md`).
48
48
  - High-risk resilience gating: when a feature touches money, billing, quota, permissions, tenant/user data isolation, privacy, high-impact AI answers, write-finality risk, repeated submission, async job finality, or incident explanation/compensation, require an explicit resilience gate before implementation or launch; do not escalate low-risk local edits only because they write files. Write-finality classification and gate detail: `references/high-risk-resilience-gates.md`.
49
49
 
@@ -8,8 +8,8 @@ Use this checklist for R&D standards, specs, guidelines, or Feishu/wiki doc fami
8
8
  2. If any child doc, second stack/service, or cross-doc product-goal reference exists, create or update a parent overview/index first and link child docs.
9
9
  3. Scope evidence must name the parent node(s) or repo scope searched, include the product Spec surface checked, list candidate child locations, and attach concrete enumeration evidence: command/output, node list, or two independent manual passes listing parent index URL plus each checked child node title/link when no programmatic tool exists. If scoped evidence is absent, mark `blocked: family enumeration unverified`, with no sign-off.
10
10
  4. Only when step 3 evidence shows zero child docs may a single existing doc be treated as its own overview/index; cite that evidence and record its path/link and authority statement.
11
- 5. Multi-doc families require an authority statement plus sync-gate rule before child docs are marked done.
12
- 6. If the family defines any implementation, stack, service, client, CI, harness, release, or QA norm, include or update a testing standard child doc. It must cover test deliverables, unit/contract/integration/E2E/manual layers, harness, CI gates, high-risk coverage, evidence format, and stack handoff; route the template to `testing-strategy`.
11
+ 5. Multi-doc families require an authority statement plus sync-gate rule before child docs are marked done. A cross-stack or cross-service product Spec lives in exactly ONE authority surface; stack and service repositories carry execution slices that link back to it and **must not** redefine the product goals it owns.
12
+ 6. If the family defines any implementation, stack, service, client, CI, harness, release, or QA norm, include or update a testing standard child doc. It must cover test deliverables, unit/contract/integration/E2E/manual layers, harness, CI gates, high-risk coverage, evidence format, and stack handoff; route the template to `testing-strategy`. That testing standard, and the shared test-layer and CI-gate policy it carries, is **owned by `testing-strategy`** — not by whichever document holds the template. Stack documents specialize commands and harness mechanics only: they **must not** replace or approve that shared policy.
13
13
  7. If the family will drive project health checks, add a conformance appendix or sibling checklist that maps each rule to `deterministic`, `agent_review`, `manual`, or `not_automatable_yet`, with severity, evidence, command/prompt owner, and CI behavior. Route architecture fitness functions to `testing-strategy`; route directory-contract coverage to `agents-file-coverage-gate`; route stack mechanics to the owning stack skills.
14
14
  8. Before invoking `tighten-doc`, record `owner-ready` with the authority statement, doc-family layer, enumeration evidence, and conformance mapping evidence when applicable, or `blocked: family enumeration unverified`.
15
15
  9. Re-confirm the doc-set enumeration at completion/sign-off, or add the sync gate if the family has grown.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: requirement-baseline
3
- description: 现状盘点 / 当前能力梳理 / 现有流程、页面、API、数据、运营规则盘点 / as-is audit / current state inventory —— 交付物是**现状清单本身**:现在怎么运作、已有哪些能力与例外、事实来源与 freshness、缺口和冲突,含按 commit 固定的代码现状取证。Skip 要的是意图、用户故事、验收标准、问题池(「到底要什么」)→ requirement-intent;要的是本轮改哪些、不改哪些、切几版(变更边界)→ requirement-scope;问线上是否已启用 → platform-observability;代码/项目质量评估 → product-rd-workflow;bug 根因 → defect-diagnosis。
3
+ description: 现状盘点 / 当前能力梳理 / 按当前代码说明现状(某状态·数据怎么产生和消费)/ 现有流程、页面、API、数据、运营规则盘点 / as-is audit / current state inventory —— 交付物是**现状清单本身**:现在怎么运作、已有哪些能力与例外、事实来源与 freshness、缺口和冲突,含按 commit 固定的代码现状取证。Skip 要的是意图、用户故事、验收标准、问题池(「到底要什么」)→ requirement-intent;要的是本轮改哪些、不改哪些、切几版(变更边界)→ requirement-scope;问线上是否已启用 → platform-observability;代码/项目质量评估 → product-rd-workflow;bug 根因 → defect-diagnosis。
4
4
  ---
5
5
 
6
6
  # Requirement Baseline
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: requirement-doc-writer
3
- description: 写 PRD / 需求文档 / 产品需求文档 / 需求说明 / user story 文档 / 验收标准文档 / 产品需求正文 —— 在 lifecycle 判定 PRD Ready 之后,把已关闭的需求组装成人读的 PRD。Skip 需求实质不清 → requirement-intent;缺现状事实 → requirement-baseline;范围/版本切片/开放决策未关闭 → requirement-scope;Agent/Machine 技术规格 → llm-inference-integration;其评测与测试层 → testing-strategy;只是润色措辞 → tighten-doc。
3
+ description: 写 PRD / 需求文档 / 产品需求文档 / 需求说明 / user story 文档 / 验收标准文档 / 产品需求正文 —— 在 lifecycle 判定 PRD Ready 之后,把已关闭的需求组装成人读的 PRD。Skip 需求实质不清 → requirement-intent;缺现状事实 → requirement-baseline;范围/版本切片/开放决策未关闭 → requirement-scope;Agent/Machine 技术规格 → llm-inference-integration;其评测与测试层 → testing-strategy;只是润色措辞 → tighten-doc;写完 PRD 还要接着往下做的多阶段研发交付·实现/发布计划 → product-rd-workflow。
4
4
  ---
5
5
 
6
6
  # Requirement Doc Writer