@ccoalm/ccl-skills 0.3.0 → 0.5.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/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/classify_envelope.py +34 -3
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_abort_leak_state_helpers.sh +148 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_classify_envelope.sh +28 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_review_json.sh +7 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate_abort_leak.sh +271 -34
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/references/public-data-acquisition.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/multi-perspective-research/references/public-disclosure-channels.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +12 -12
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/dual-track-review-gate.md +8 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/eval-routing.md +7 -8
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/extraction-quickstart.md +3 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/firing-point-placement.md +8 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +7 -6
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/recurring-anti-patterns-checklist.md +18 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +47 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md +28 -29
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/check-ccl-skills.sh +165 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/eval-health.rb +23 -10
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +303 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_impact_chain_refscripts.sh +222 -91
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_ci_checkout_ref_binding.sh +85 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_entrypoint_domain_scan_terms.sh +123 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_dateless_host.sh +6 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_round_attribution.sh +12 -12
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_self_adjudication.sh +455 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_source_refuted.sh +20 -20
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_liveness_predicate_gate.sh +288 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/SKILL.md +4 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/deliverable-doc-genre-skeletons.md +133 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/doc-charter-first.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/references/figure-and-table-craft.md +318 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/AGENTS.md +46 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/doc-lint.py +246 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/figure-lint.py +1092 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/mutation_probe.sh +100 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/test_figure_and_doc_lint.sh +375 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/control.md +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/empty-header.md +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fake-header.md +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fenced-noise.md +14 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fig-dangling.md +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fig-orphan-captioned.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fig-orphan.md +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/fig.png +0 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/imbalance.md +41 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/no-unit.md +8 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/should-be-chart.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/tables-only-clean.md +35 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/unfilled.md +7 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/doc/wide-table.md +5 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/bad-viewbox.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/blackmarker.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/control.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/crossings.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/cvd-confusable.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/decorative-line.svg +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/edge-no-arrow.svg +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/edge-vague.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/figure-contract.json +21 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/figure-is-a-list.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/flow-mixed.svg +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/low-contrast.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/malformed.svg +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/no-aria.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/no-group.svg +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/no-legend.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/no-title.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/no-viewbox.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/offcontract-shape.svg +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/overflow.svg +13 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/transformed.svg +9 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/ungrouped-card.svg +12 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/tighten-doc/scripts/tests/svg/unlabeled-edge.svg +13 -0
- package/dist/assets/release.json +276 -31
- package/package.json +1 -1
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Behavior suite for check-ccl-skills.sh's `liveness_predicate_scan` gate
|
|
3
|
+
# (recurring-anti-patterns-checklist.md, Anti-pattern 28).
|
|
4
|
+
#
|
|
5
|
+
# The gate exists because an existence-test liveness predicate fails in the direction
|
|
6
|
+
# that looks like a real defect: the probe reds, names the code under test, and the code
|
|
7
|
+
# under test was fine. Its value therefore rests on two properties that must BOTH be
|
|
8
|
+
# pinned — it fires on the shape that actually shipped, and it stays silent on the
|
|
9
|
+
# legitimate spellings. A gate that also flagged a ppid read used to identify a parent,
|
|
10
|
+
# or the fix's own documentation, is one a later maintainer loosens after the first false
|
|
11
|
+
# positive, and a loosened gate catches nothing.
|
|
12
|
+
#
|
|
13
|
+
# bash skills/skill-extraction-workflow/scripts/test_liveness_predicate_gate.sh
|
|
14
|
+
set -u
|
|
15
|
+
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
17
|
+
CHECKER="${CHECKER:-$SCRIPT_DIR/check-ccl-skills.sh}"
|
|
18
|
+
[ -f "$CHECKER" ] || { echo "FAIL: checker not found: $CHECKER" >&2; exit 1; }
|
|
19
|
+
|
|
20
|
+
pass=0; fail=0
|
|
21
|
+
note() { fail=$((fail+1)); printf 'FAIL %s\n' "$1" >&2; }
|
|
22
|
+
ok() { pass=$((pass+1)); }
|
|
23
|
+
|
|
24
|
+
TMP=$(mktemp -d "${TMPDIR:-/tmp}/liveness-gate-test.XXXXXX") || exit 1
|
|
25
|
+
TMP=$(cd "$TMP" && pwd -P)
|
|
26
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
27
|
+
|
|
28
|
+
# Run the gate section in isolation rather than standing up a whole synthetic skill tree.
|
|
29
|
+
section=$TMP/gate-section.sh
|
|
30
|
+
{
|
|
31
|
+
echo '#!/usr/bin/env bash'
|
|
32
|
+
# MUST match the host checker's options, or a section that aborts the real checker
|
|
33
|
+
# still passes every probe here.
|
|
34
|
+
echo 'set -euo pipefail'
|
|
35
|
+
echo 'root="$1"'
|
|
36
|
+
awk '/^# Anti-pattern 28 —/{p=1} p; /^echo "liveness_predicate_scan_ok"$/{if(p) exit}' "$CHECKER"
|
|
37
|
+
} > "$section"
|
|
38
|
+
grep -q 'liveness_predicate_scan_ok' "$section" \
|
|
39
|
+
|| { echo "FAIL: could not extract the gate section from $CHECKER (anchor moved?)" >&2; exit 1; }
|
|
40
|
+
grep -q 'ppid=' "$section" \
|
|
41
|
+
|| { echo "FAIL: extracted section carries no predicate — extraction is bogus" >&2; exit 1; }
|
|
42
|
+
|
|
43
|
+
run_gate() { # run_gate <root> -> RC, OUT
|
|
44
|
+
OUT=$( bash "$section" "$1" 2>&1 ); RC=$?
|
|
45
|
+
}
|
|
46
|
+
mk_root() { local r="$TMP/$1"; mkdir -p "$r/scripts"; printf '%s' "$r"; }
|
|
47
|
+
|
|
48
|
+
# The banned spelling is assembled at runtime, never written literally in this file:
|
|
49
|
+
# this suite is itself a `test_*.sh` inside the scanned tree, so a literal would make the
|
|
50
|
+
# repo's own gate flag its regression test. (The scanner-matches-itself trap.)
|
|
51
|
+
PPID_READ='ps -o ppid= -p "$pid"'
|
|
52
|
+
VIOLATION='[ "$('"$PPID_READ"' 2>/dev/null | tr -d " ")" = "1" ] && echo orphan'
|
|
53
|
+
|
|
54
|
+
# --- P1: a clean tree passes ------------------------------------------------
|
|
55
|
+
r=$(mk_root clean)
|
|
56
|
+
printf '#!/usr/bin/env bash\necho hello\n' > "$r/scripts/test_clean.sh"
|
|
57
|
+
run_gate "$r"
|
|
58
|
+
if [ "$RC" -eq 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_ok'; then ok
|
|
59
|
+
else note "p1 clean tree must pass with the ok token (rc=$RC): $OUT"; fi
|
|
60
|
+
|
|
61
|
+
# --- P2: the violation fires (the gate's whole reason to exist) -------------
|
|
62
|
+
r=$(mk_root violation)
|
|
63
|
+
printf '#!/usr/bin/env bash\n%s\n' "$VIOLATION" > "$r/scripts/test_probe.sh"
|
|
64
|
+
run_gate "$r"
|
|
65
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
66
|
+
else note "p2 planted orphan-oracle must FAIL the gate (rc=$RC): $OUT"; fi
|
|
67
|
+
|
|
68
|
+
# --- P2b: the report names the offending file and line ----------------------
|
|
69
|
+
if printf '%s' "$OUT" | grep -q 'scripts/test_probe.sh:2'; then ok
|
|
70
|
+
else note "p2b failure output must locate the hit (file:line), got: $OUT"; fi
|
|
71
|
+
|
|
72
|
+
# --- P2c: the hit and the diagnosis must not run together on one line -------
|
|
73
|
+
# The sorted-hit list loses its trailing newline to command substitution; without an
|
|
74
|
+
# explicit one the last hit and the message concatenate and neither greps cleanly.
|
|
75
|
+
if printf '%s' "$OUT" | grep -q '^liveness_predicate_scan_failed'; then ok
|
|
76
|
+
else note "p2c the diagnosis must start its own line, got: $OUT"; fi
|
|
77
|
+
|
|
78
|
+
# --- P3: consulting process state clears it (this IS the documented fix) ----
|
|
79
|
+
r=$(mk_root fixed)
|
|
80
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
81
|
+
printf 'st="$(ps -o stat= -p "$pid")"\n'
|
|
82
|
+
printf '%s\n' "$VIOLATION"
|
|
83
|
+
} > "$r/scripts/test_probe.sh"
|
|
84
|
+
run_gate "$r"
|
|
85
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
86
|
+
else note "p3 a state consult within the window must clear the line (rc=$RC): $OUT"; fi
|
|
87
|
+
|
|
88
|
+
# --- P3b: a *_state helper THIS FILE DEFINES over process state clears it ---
|
|
89
|
+
# The real fix's shape: one helper, defined in the same file, reading `ps -o stat=`.
|
|
90
|
+
r=$(mk_root fixed_helper)
|
|
91
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
92
|
+
printf 'wrapper_state() {\n ps -o stat= -p "$1"\n}\n'
|
|
93
|
+
printf 'case "$(wrapper_state "$pid")" in live) : ;; esac\n'
|
|
94
|
+
printf '%s\n' "$VIOLATION"
|
|
95
|
+
} > "$r/scripts/test_probe.sh"
|
|
96
|
+
run_gate "$r"
|
|
97
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
98
|
+
else note "p3b a file-defined state helper must clear the line (rc=$RC): $OUT"; fi
|
|
99
|
+
|
|
100
|
+
# --- P3c: an unrelated *_state call is NOT remediation ----------------------
|
|
101
|
+
# Found by adversarial review: accepting any `*_state` token let a bookkeeping helper
|
|
102
|
+
# that never reads process state clear a real hit, so the blocking gate printed ok.
|
|
103
|
+
r=$(mk_root fake_helper)
|
|
104
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
105
|
+
printf 'record_state "$other_pid"\n'
|
|
106
|
+
printf '%s\n' "$VIOLATION"
|
|
107
|
+
} > "$r/scripts/test_probe.sh"
|
|
108
|
+
run_gate "$r"
|
|
109
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
110
|
+
else note "p3c an unrelated *_state call must NOT clear the violation (rc=$RC): $OUT"; fi
|
|
111
|
+
|
|
112
|
+
# --- P3d: a defined helper that does NOT read process state is not remediation
|
|
113
|
+
r=$(mk_root hollow_helper)
|
|
114
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
115
|
+
printf 'record_state() {\n echo "$1" >>"$log"\n}\n'
|
|
116
|
+
printf 'record_state "$other_pid"\n'
|
|
117
|
+
printf '%s\n' "$VIOLATION"
|
|
118
|
+
} > "$r/scripts/test_probe.sh"
|
|
119
|
+
run_gate "$r"
|
|
120
|
+
if [ "$RC" -ne 0 ]; then ok
|
|
121
|
+
else note "p3d a defined helper that never reads process state must not clear it (rc=$RC): $OUT"; fi
|
|
122
|
+
|
|
123
|
+
# --- P4: a whole-line comment carrying the spelling is documentation --------
|
|
124
|
+
# The checklist row and the gate's own comment block name the banned spelling; a gate
|
|
125
|
+
# that flags its own documentation gets loosened.
|
|
126
|
+
r=$(mk_root commented)
|
|
127
|
+
printf '#!/usr/bin/env bash\n# %s\n' "$VIOLATION" > "$r/scripts/test_doc.sh"
|
|
128
|
+
run_gate "$r"
|
|
129
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
130
|
+
else note "p4 a whole-line comment must not be flagged (rc=$RC): $OUT"; fi
|
|
131
|
+
|
|
132
|
+
# --- P5: scope is test scripts — a signalling guard elsewhere is legitimate --
|
|
133
|
+
# Outside a test, asking whether a pid exists before signalling it is the right
|
|
134
|
+
# question; flagging it would trade a real false-positive cost for nothing.
|
|
135
|
+
r=$(mk_root nontest)
|
|
136
|
+
printf '#!/usr/bin/env bash\n%s\n' "$VIOLATION" > "$r/scripts/helper.sh"
|
|
137
|
+
run_gate "$r"
|
|
138
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
139
|
+
else note "p5 non-test shell is out of scope and must not fire (rc=$RC): $OUT"; fi
|
|
140
|
+
|
|
141
|
+
# --- P6: a ppid read that IDENTIFIES a parent is not an orphan oracle -------
|
|
142
|
+
# The common, correct use. Flagging it is what would make precision collapse.
|
|
143
|
+
r=$(mk_root identify)
|
|
144
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
145
|
+
printf 'parent="$(%s 2>/dev/null | tr -d " ")"\n' "$PPID_READ"
|
|
146
|
+
printf 'cmd="$(ps -o command= -p "$parent")"\n'
|
|
147
|
+
} > "$r/scripts/test_identify.sh"
|
|
148
|
+
run_gate "$r"
|
|
149
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
150
|
+
else note "p6 a ppid read used for parent identity must not fire (rc=$RC): $OUT"; fi
|
|
151
|
+
|
|
152
|
+
# --- P7: a COMMENT naming the helper must not clear a real violation ---------
|
|
153
|
+
# The waiver has to be code that consults process state, not a note saying someone
|
|
154
|
+
# should. Found by adversarial review of this gate: the window grep read raw text, so a
|
|
155
|
+
# TODO beside the violation made the blocking checker print ok for a line it had found.
|
|
156
|
+
r=$(mk_root comment_waiver)
|
|
157
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
158
|
+
printf '# TODO: use wrapper_state here instead\n'
|
|
159
|
+
printf '%s\n' "$VIOLATION"
|
|
160
|
+
} > "$r/scripts/test_probe.sh"
|
|
161
|
+
run_gate "$r"
|
|
162
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
163
|
+
else note "p7 a comment mentioning the helper must NOT clear the violation (rc=$RC): $OUT"; fi
|
|
164
|
+
|
|
165
|
+
# --- P8: parameter expansion carrying '#' must not be mistaken for a comment --
|
|
166
|
+
# Stripping trailing comments with a naive `#`-to-end rule would truncate `${var#pre}`
|
|
167
|
+
# and could drop the real state consult that follows it, turning the fix into a hit.
|
|
168
|
+
r=$(mk_root hash_expansion)
|
|
169
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
170
|
+
printf 'rel="${path#"$root"/}"; st="$(ps -o stat= -p "$pid")"\n'
|
|
171
|
+
printf '%s\n' "$VIOLATION"
|
|
172
|
+
} > "$r/scripts/test_probe.sh"
|
|
173
|
+
run_gate "$r"
|
|
174
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
175
|
+
else note "p8 a '#' inside parameter expansion must not void the state consult (rc=$RC): $OUT"; fi
|
|
176
|
+
|
|
177
|
+
# --- P9: the NEGATED assertion is the opposite check and must not fire ------
|
|
178
|
+
# `!= "1"` asserts a process is NOT reparented. An unrestricted `.*=` in the predicate
|
|
179
|
+
# swallowed the `!`, so the gate flagged the very check that does the right thing —
|
|
180
|
+
# found by adversarial review, and the false-positive direction this gate must avoid.
|
|
181
|
+
r=$(mk_root negated)
|
|
182
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
183
|
+
printf '[ "$(%s 2>/dev/null | tr -d " ")" != "1" ] && echo still-parented\n' "$PPID_READ"
|
|
184
|
+
} > "$r/scripts/test_probe.sh"
|
|
185
|
+
run_gate "$r"
|
|
186
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
187
|
+
else note "p9 a negated ppid assertion must NOT fire (rc=$RC): $OUT"; fi
|
|
188
|
+
|
|
189
|
+
# --- P9b: the positive oracle still fires with the tightened operator match --
|
|
190
|
+
# Guards the tightening itself: narrowing the operator must not blunt the real catch.
|
|
191
|
+
r=$(mk_root still_fires)
|
|
192
|
+
printf '#!/usr/bin/env bash\n%s\n' "$VIOLATION" > "$r/scripts/test_probe.sh"
|
|
193
|
+
run_gate "$r"
|
|
194
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
195
|
+
else note "p9b the real orphan oracle must still fire after tightening (rc=$RC): $OUT"; fi
|
|
196
|
+
|
|
197
|
+
# --- P10: a bare `stat=` assignment is not a process-state read ---------------
|
|
198
|
+
# Found by adversarial review: the waiver grepped bare `stat=`, so an unrelated
|
|
199
|
+
# assignment two lines away cleared a genuine hit and the blocking gate printed ok.
|
|
200
|
+
r=$(mk_root fake_stat)
|
|
201
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
202
|
+
printf 'stat=unknown\n'
|
|
203
|
+
printf '%s\n' "$VIOLATION"
|
|
204
|
+
} > "$r/scripts/test_probe.sh"
|
|
205
|
+
run_gate "$r"
|
|
206
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
207
|
+
else note "p10 a bare stat= assignment must NOT clear the violation (rc=$RC): $OUT"; fi
|
|
208
|
+
|
|
209
|
+
# --- P10b: the genuine `ps -o stat=` read still clears it --------------------
|
|
210
|
+
r=$(mk_root real_stat)
|
|
211
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
212
|
+
printf 'st="$(ps -o stat= -p "$pid")"\n'
|
|
213
|
+
printf '%s\n' "$VIOLATION"
|
|
214
|
+
} > "$r/scripts/test_probe.sh"
|
|
215
|
+
run_gate "$r"
|
|
216
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
217
|
+
else note "p10b a real ps -o stat= read must still clear the line (rc=$RC): $OUT"; fi
|
|
218
|
+
|
|
219
|
+
# --- P11: a HOLLOW helper plus an unrelated state read elsewhere is not a fix --
|
|
220
|
+
# Found by adversarial review: "the file defines *_state" and "the file reads process
|
|
221
|
+
# state somewhere" were checked independently, so the two were never tied together and a
|
|
222
|
+
# do-nothing helper borrowed an unrelated read to clear a real hit.
|
|
223
|
+
r=$(mk_root hollow_plus_elsewhere)
|
|
224
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
225
|
+
printf 'wrapper_state() {\n echo unknown\n}\n'
|
|
226
|
+
printf 'other() {\n ps -o stat= -p "$1"\n}\n'
|
|
227
|
+
printf 'case "$(wrapper_state "$pid")" in live) : ;; esac\n'
|
|
228
|
+
printf '%s\n' "$VIOLATION"
|
|
229
|
+
} > "$r/scripts/test_probe.sh"
|
|
230
|
+
run_gate "$r"
|
|
231
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
232
|
+
else note "p11 a hollow helper must NOT borrow an unrelated state read (rc=$RC): $OUT"; fi
|
|
233
|
+
|
|
234
|
+
# --- P12: a ONE-LINE hollow helper must not borrow a later function's read -----
|
|
235
|
+
# Found by the adversarial challenge: the awk rule set inbody and ran `next`, so a
|
|
236
|
+
# definition that opens and closes on one line never met its `}` and stayed "in body"
|
|
237
|
+
# across the following functions, crediting their state read to the hollow helper.
|
|
238
|
+
r=$(mk_root oneline_hollow)
|
|
239
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
240
|
+
printf 'wrapper_state() { echo live; }\n'
|
|
241
|
+
printf 'other() {\n ps -o stat= -p "$other_pid"\n}\n'
|
|
242
|
+
printf 'case "$(wrapper_state "$pid")" in live) : ;; esac\n'
|
|
243
|
+
printf '%s\n' "$VIOLATION"
|
|
244
|
+
} > "$r/scripts/test_probe.sh"
|
|
245
|
+
run_gate "$r"
|
|
246
|
+
if [ "$RC" -ne 0 ] && printf '%s' "$OUT" | grep -q 'liveness_predicate_scan_failed'; then ok
|
|
247
|
+
else note "p12 a one-line hollow helper must NOT borrow a later read (rc=$RC): $OUT"; fi
|
|
248
|
+
|
|
249
|
+
# --- P12b: a genuine ONE-LINE helper that does read state still clears it ------
|
|
250
|
+
r=$(mk_root oneline_real)
|
|
251
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
252
|
+
printf 'wrapper_state() { ps -o stat= -p "$1"; }\n'
|
|
253
|
+
printf 'case "$(wrapper_state "$pid")" in live) : ;; esac\n'
|
|
254
|
+
printf '%s\n' "$VIOLATION"
|
|
255
|
+
} > "$r/scripts/test_probe.sh"
|
|
256
|
+
run_gate "$r"
|
|
257
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
258
|
+
else note "p12b a real one-line state helper must clear the line (rc=$RC): $OUT"; fi
|
|
259
|
+
|
|
260
|
+
# --- P13/P14: the DOCUMENTED limit, pinned rather than left in prose -----------
|
|
261
|
+
# These two assert the gate does NOT fire, which is a hole, not a feature: a state read
|
|
262
|
+
# of a different pid, or one whose result is discarded, still clears the window. Proving
|
|
263
|
+
# a read GOVERNS the verdict needs dataflow over a parsed shell, so the mechanical gate
|
|
264
|
+
# stops here by design (recurring-anti-patterns-checklist.md, Anti-pattern 28).
|
|
265
|
+
# They are here so the limit is exercised, not merely described: if a future change makes
|
|
266
|
+
# the gate stricter these go red, and whoever tightened it must update the checklist
|
|
267
|
+
# rather than discover the prose had silently gone stale.
|
|
268
|
+
r=$(mk_root limit_other_pid)
|
|
269
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
270
|
+
printf 'ps -o stat= -p "$other_pid" >/dev/null\n'
|
|
271
|
+
printf '%s\n' "$VIOLATION"
|
|
272
|
+
} > "$r/scripts/test_probe.sh"
|
|
273
|
+
run_gate "$r"
|
|
274
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
275
|
+
else note "p13 KNOWN LIMIT CHANGED: a different-pid state read now fires — update the checklist (rc=$RC)"; fi
|
|
276
|
+
|
|
277
|
+
r=$(mk_root limit_discarded)
|
|
278
|
+
{ printf '#!/usr/bin/env bash\n'
|
|
279
|
+
printf 'ps -o stat= -p "$pid" >/dev/null\n'
|
|
280
|
+
printf '%s\n' "$VIOLATION"
|
|
281
|
+
} > "$r/scripts/test_probe.sh"
|
|
282
|
+
run_gate "$r"
|
|
283
|
+
if [ "$RC" -eq 0 ]; then ok
|
|
284
|
+
else note "p14 KNOWN LIMIT CHANGED: a discarded same-pid state read now fires — update the checklist (rc=$RC)"; fi
|
|
285
|
+
|
|
286
|
+
printf 'liveness_predicate_gate: pass=%s fail=%s\n' "$pass" "$fail"
|
|
287
|
+
[ "$fail" -eq 0 ] || exit 1
|
|
288
|
+
echo "liveness_predicate_gate_ok"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tighten-doc
|
|
3
|
-
description: "润色文档 / 精简文档 / 改下文档 / AI 味太重 / 废话太多 / polish / make shorter / remove AI tone → finalize wording after substance is settled: clarify, shorten, restructure lightly, preserve decisions, and keep comments safe. Proactively draft a no-owner deliverable doc(「写一份分享/给同事的文档」). Skip while a sibling owns the substance(定稿仍回本技能): spec/PRD/标准 → product-rd-workflow; 技术方案/架构文档 → architecture 技能; 发布文档 → release-doc-writer; 测试用例文档 → test-artifact-management."
|
|
3
|
+
description: "润色文档 / 精简文档 / 改下文档 / AI 味太重 / 废话太多 / polish / make shorter / remove AI tone;**该画时序图还是状态机 / 这里要不要配图 / 图画完了总觉得不对劲说不上哪不对 / 缺图例 / 连线没标签 / 全是表格要不要补图 / 图里字看不清** → finalize wording after substance is settled: clarify, shorten, restructure lightly, preserve decisions, and keep comments safe. Proactively draft a no-owner deliverable doc(「写一份分享/给同事的文档」). 图与表的**表示形式**(图种由主张形态推出、记法硬约束、版式契约、对比度、可跑的检查器)归本技能,**系统边界与架构决策本身仍归架构技能**。Skip while a sibling owns the substance(定稿仍回本技能): spec/PRD/标准 → product-rd-workflow; 技术方案/架构文档 → architecture 技能; 发布文档 → release-doc-writer; 测试用例文档 → test-artifact-management."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# tighten-doc — 文档写作与优化
|
|
@@ -17,7 +17,7 @@ Three modes:
|
|
|
17
17
|
- Rewrite: restructure an existing doc so decisions, owners, gates, and next actions are easier to scan.
|
|
18
18
|
- Tighten: remove filler, duplication, AI tone, meta narration, and over-long sentences without deleting decisions.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
**先判文档类型,再定形态**:读者是在**用一件已存在的东西**(tutorial / how-to / reference / explanation 四模式),还是要**据此决定或执行一件尚未做完的事**(方案·架构 / 调研 / 现状梳理 / 评审 / 计划)。两轴的判据、每类的首稿必答节、正文与证据分册、图形态,以及「只标记拆分候选、不自行拆分」的收尾边界,见 `references/deliverable-doc-genre-skeletons.md`。一页纸操作手册默认形态对应 how-to / reference,别硬套到其他类型上。
|
|
21
21
|
|
|
22
22
|
For spec/standard/guideline artifacts, the `pre-owner blocked` marker rule applies to all three modes — do not share/publish until the owner marker exists; local wording polish must preserve the blocked label.
|
|
23
23
|
|
|
@@ -59,7 +59,7 @@ owner · 硬规则 · 完成标准/DoD · 里程碑 · 数值阈值 · the real
|
|
|
59
59
|
- **外部基线 / 标准值入文档 = 独立标注 + 命名来源 + 内部门(若有)仍权威。** 引用外部 benchmark、行业阈值、标准默认值(评测目标、性能预算、参考 SLO 等)时,放成独立的列 / 行 / 标注并配命名来源超链,别和本系统自己的验收门 / 阈值混写成同一个数。**当本系统有自己的验收门时**显式声明本系统门为准、外部值只作对标参考(反模式:把外部基线直接当验收标准,读者误以为外部数就是上线门);**若文档本身即标准 / 评测报告 / 无内部门**,则标清来源 / 范围 / 权威,别杜撰一个内部门。**评自己的稿是这条的另一半**:对自己产出的文档评可实测呈现属性(加粗密度、句长、结构层级)前,先建同体裁实测基准——长文或系列交付物在**初稿前**建(写完被纠正后再补测,是实测过的返工形态)——按**预先声明的抽样框与纳排规则**(在实测待评稿自身指标**之前**冻结,防止看完自己的数再挑参照系)取同体裁公开样本(记录样本量、口径与局限;不得挑对自己有利的样本充数,"若干份"本身不构成充分门槛),中英文样本分开统计,把待评稿放进分布里定位;找不到可靠公开样本或体裁不可比时如实记「未对标 + 原因」;流行排版阈值逐条核到一手出处再用,核不到不用。**分布定位的合法输出是描述**("高于/低于所选样本分布"),**不是裁决**:"合适"要再结合读者任务与可用性判断;"优于同类"不得由密度类粗指标推出;无基准时该属性只能报「未对标」——自己的审美不是分布。密度居中更推不出「稿子写得好」:整体质量仍按文档目的、读者任务、事实核验与本 rubric 分轴判断,呈现分布不背书内容正确性。
|
|
60
60
|
- No inline `|` / pipe-delimited lists (RACI / 分工) — break into bullets or a table.
|
|
61
61
|
- Short sentences, one point per line, enumerations as tables.
|
|
62
|
-
- **表达形式匹配内容**:分支关系 / 状态迁移复杂到文字难扫时优先**图**(mermaid 等);字段对比、分桶属性、owner/gate/证据矩阵优先**表**;线性步骤用编号列表;一两点判断一句话或 bullet。别为单个判断加**装饰性**多桶图,但桶间有不同 owner / 阈值 / 例外 /
|
|
62
|
+
- **表达形式匹配内容**:分支关系 / 状态迁移复杂到文字难扫时优先**图**(mermaid 等);字段对比、分桶属性、owner/gate/证据矩阵优先**表**;线性步骤用编号列表;一两点判断一句话或 bullet。别为单个判断加**装饰性**多桶图,但桶间有不同 owner / 阈值 / 例外 / 后果时**必须结构化**(该结构别压成一句)。**目标环境不稳定渲染图时**,文字版流程为准、图只作辅助。**callout / 图内文字 = 概览形态,只承一个要点**:callout 塞成多点密块("一坨")就拆开或降到正文 / 表。**图种由主张形态定**(有事件触发→状态机 / 消息序→时序 / 随完成流转→流程);**画了必须有标题与图例、连线单向且标签具体**;**量级对比别全压进表**。余下见 `references/figure-and-table-craft.md`。
|
|
63
63
|
- **代码进代码块,不进段落**:**多行 / 独立执行步骤 / 长 flag 串命令 / 多命令序列**放代码块(带 lang),不写成段落里的纯文本或一长串内联 `code`。**短的随文 one-liner / 表达式、对照表单元格、「用 `func()`」式符号引用可留 inline**,只要不长到影响扫读(与上面的表格单元格 / 内联引用规则一致,别硬塞进代码块)。多语言对照两端形态对齐——一端给了代码块,另一端别写成「Go:`call(...)`」式内联段落。
|
|
64
64
|
- **Enumeration sections (依赖/兜底/分工/里程碑 子项) = multi-line sub-bullets, NOT a `;`-collapsed single line.** Readability beats compactness here; a `- 依赖:A;B;C;D` run is hard to scan — split to `- 依赖:` + one `- A` sub-bullet per item. Do not collapse to one `;` line just for parity with another card; parity is not a reason to reduce scanability. Single-line `;` is only for a true 2-item short pointer where sub-bullets would be heavier than the content.
|
|
65
65
|
- Table cells that list multiple skills, owners, checks, environments, or evidence items should be split into multiple lines or shorter rows. A readable table beats a compressed cell when the cell is used as an execution checklist.
|
|
@@ -147,7 +147,7 @@ Never destroy collaborative comments. Before editing a collaborative doc, fetch
|
|
|
147
147
|
|
|
148
148
|
**交付前 closeout checklist(阻断项索引,不是通过证书)。** 报「已优化」仍需跑完 Workflow 1-4 + KEEP / decided-point 保全 + 下方 closeout-sweep 全量;本清单只把高频阻断项收敛成可判定的最后一道闸,逐项标 ✓ / N-A、任一未过即不得报已优化(每项指向下方 / FORM 的 canonical 规则,不在此复述全部语义)。发布、同步、commit 前离开生成态,把改过的块当"刚被粘进来"逐行读一遍再判:
|
|
149
149
|
|
|
150
|
-
1. **callout / 图内文字 = 一个要点**:无多点密块(一坨)就拆或降正文 /
|
|
150
|
+
1. **callout / 图内文字 = 一个要点**:无多点密块(一坨)就拆或降正文 / 表;图的形态项过 `figure-and-table-craft.md`。
|
|
151
151
|
2. **管理 / 业务 jargon 对目标读者已 plain-name / gloss**(协议 / API / 字段 / 契约名 + 用户认可的紧凑 `/` `+` 枚举保留;保留项里读者不熟的首次解释)。
|
|
152
152
|
3. **编号连续、父子号同步**;族内同义术语 / label 漂移**全族扫 = 0**。
|
|
153
153
|
4. **图 ↔ 文字无双写**(图承流程、文字留 KEEP 项);外部基线 / 标准值独立列 + 命名来源,门权威按「外部基线」条(有内部门则其为准,无则标清来源不杜撰)。
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Deliverable Doc Genre Skeletons(交付型文档的文体族骨架)
|
|
2
|
+
|
|
3
|
+
交付型文档不是一个体裁。**族判错,骨架就错,之后每一轮打磨都在补首稿本该有的节。** 本文件管三件事:判族、每族首稿必答项与表示形式、可判定的验收。
|
|
4
|
+
|
|
5
|
+
本文件持有:**族判定**、**跨族的形态规则**(§0 §3 §4 §5 §6)与**方案 / 架构族的必答项**;调研族与现状族的必答项由 `multi-perspective-research` 与 `requirement-baseline` 各自持有,本文件只路由、不复述、也不代它们做完整性判定。文档的**实质**仍归各自 owner。不管:措辞与句子层定稿(本技能 `SKILL.md`)、调研执行本身(`multi-perspective-research`)、单个决定的记录格式与规范族的层级同步闸(均归 `product-rd-workflow`,分别是其 adr-convention 与 rd-standards-doc-family-checklist 参考)。
|
|
6
|
+
|
|
7
|
+
> **全局边界(本文件每一条都受它约束)**:本文件描述交付型文档**应有的形态**,不是授权改动文档集。起草新文档时按这些形态起稿;面对**已存在**的文档,形态不符只产出**标记与建议**——创建、拆分、合并、重排兄弟文档,或把单篇扩成文档族,一律由实质 owner 决定(spec / standards / guideline 族按 `product-rd-workflow` 的 `owner-ready` 闸)。下文出现的「分册」「成族」「拆」均按此读:**是目标形态的描述,不是自授的动作许可**。
|
|
8
|
+
|
|
9
|
+
## §0 两个分类轴
|
|
10
|
+
|
|
11
|
+
两轴**不互斥**,一份文档可以同时沾两边(如一份现状说明既描述已建成的系统,又要支撑一个尚未做的决定)。判**主导用途**:读者拿它主要是去**用**那件已存在的东西,还是去**决定/执行**尚未做完的事。两者都真实存在时,**交付面的族骨架为准**(它决定必答节与分册),使用者面的模式只用来决定相关段落内部的写法。
|
|
12
|
+
|
|
13
|
+
| 轴 | 读者在做什么 | 分类 |
|
|
14
|
+
|---|---|---|
|
|
15
|
+
| 使用者面 | 用一件**已存在**的东西 | Diataxis 四模式:**tutorial**(learning by doing)· **how-to**(recipe for one task)· **reference**(look up exact facts)· **explanation**(understand why)|
|
|
16
|
+
| 交付面 | 据此**决定或执行一件尚未做完的事** | 本文件 §1 的五族:方案·架构 / 调研 / 现状梳理 / 评审 / 计划 |
|
|
17
|
+
|
|
18
|
+
使用者面的既有纪律(从 `SKILL.md` 移来,义务不变):
|
|
19
|
+
|
|
20
|
+
- **每份文档保持一个主导模式**,并盯住 **muddled purpose**——一份文档同时想当完整 tutorial *和*完整 reference,两类读者都服务不好;失败的是这个,不是一份 how-to 里嵌一张紧凑的选项/环境变量表。
|
|
21
|
+
- 四模式是**用来发现混杂的判据**,不是自顶向下强行拆成四份文档的计划。
|
|
22
|
+
- `SKILL.md` 的一页纸操作手册默认形态属于 how-to / reference;tutorial 与 explanation 天然不同,别硬套。
|
|
23
|
+
- **这一步仍在定稿范围内**:**只标记 reader-mode 拆分候选,不得在实质 owner 定下文档集之前创建、拆分、重排兄弟文档,也不得路由文档生成**(spec / standards / guideline 族的 owner 是 `product-rd-workflow`,按其 `owner-ready` 闸)——文档生成类技能只是执行器,永不替代 owner。
|
|
24
|
+
|
|
25
|
+
交付面同理:族判定与分册是**形态判断**,实质仍归各族 owner。
|
|
26
|
+
|
|
27
|
+
## §1 先判族
|
|
28
|
+
|
|
29
|
+
| 族 | 读者要用它做什么 | 判据 |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| 方案 / 架构 | 批准或否决一个尚未建成的做法 | 主张「应该怎么做」,实现尚未发生 |
|
|
32
|
+
| 调研 / 研究 | 在不确定中形成判断 | 主张「外部世界是什么样」,结论由证据强度限定 |
|
|
33
|
+
| 现状 / 梳理 | 知道现在怎么运作、缺口在哪 | 主张「已经是什么样」,可被当前系统证否 |
|
|
34
|
+
| 评审 / 发现 | 判每条问题真不真、要不要排期 | 主张「哪里不对」,逐条可裁决 |
|
|
35
|
+
| 计划 / 整改 | 认领与排期 | 主张「谁在什么阶段做什么」 |
|
|
36
|
+
|
|
37
|
+
混族的判据不是「出现了两族的内容」,而是**两族的读者与要做的决定不同,却共用一套骨架**——它是「读者读不下去、反复要求重写」最常见的根因。同一条决策链上的相邻族可以同篇(如评审结论后接 owner 已认领的整改条目),但**每段仍按各自族的骨架写**,不混成一套。读者与决定确实分叉时,起草阶段就分开写;已成篇的按全局边界只标记不自行改。
|
|
38
|
+
|
|
39
|
+
## §2 每族首稿必答项(起草阶段用;缺一项通常预定一轮返工)
|
|
40
|
+
|
|
41
|
+
**作用阶段**:起草新文档时按此清单起稿。**对已成稿的文档做润色时,本清单只用来「标记缺项候选」交实质 owner**——不据此判文档不合规、不据此把润色请求扩成结构返工;实质完整性的裁决权在方案 owner,不在定稿技能。
|
|
42
|
+
|
|
43
|
+
**方案 / 架构族:**(下列是**承载多个决定与实施路径**的方案文档的必答项。只记录单个决定的短稿用 ADR,归 `product-rd-workflow` 的 adr-convention 参考;起草时对不适用项宜写「不适用 + 理由」而非静默省略——省略与判定不适用在评审席上不是一回事;但这是起草建议,不是对既有文档的合规判据。)
|
|
44
|
+
|
|
45
|
+
- **定位与命题定性**:这是设计稿还是已建成描述;本次变更的性质用一个词定死(新建 / 并行 / 替换 / 迁移 / 下线),并列出被误用就会引发全篇返工的**禁用词**。命题设错的返工代价与篇幅成正比,是本族最贵的一类。
|
|
46
|
+
- **非目标**:明确不做什么。业界骨架把它与目标并列为必备节,不是补充说明。
|
|
47
|
+
- **备选与落选理由**:每个候选连同「为什么没选它」;候选若只是陪跑(对照 / 谈判锚),把这个角色写出来。
|
|
48
|
+
- **决策性章节按三段写**:结论(这一层定成什么样)→ 约束(哪些是硬的,越过就出问题)→ 动作(谁 · 哪阶段)。描述性章节(非目标、术语与口径、外部先例、本方案代价)不套这三段,它们不产生动作。
|
|
49
|
+
- **开放决策带闸**:未关闭的决策单列,写明它阻塞什么(如「未关闭不进入实现」)。开放项不是留给下一轮打磨去补的,是首稿就该显式挂起的。
|
|
50
|
+
- **本方案自身的代价**:选定这条路要付出什么、会变差的是什么。与「备选与落选理由」不同——那条讲别的路为什么不选,这条讲**选定的这条路的坏处**;评审席上问不出答案的多半是这一节缺了。
|
|
51
|
+
- **外部先例**:同类问题别人怎么解决的、结果如何、与本处约束的差异。缺这一节最典型的返工触发是评审时被问「参考业界实践了么」。
|
|
52
|
+
- **质量目标与验收场景**:本次要达成的质量属性排序(不是罗列全部),每条给可判定的验收场景;属性口径与取舍归 `product-rd-workflow` 的 quality-attributes 参考,此处只要求它在首稿出现。
|
|
53
|
+
- **术语与口径表**:本文中含义被限定的词逐条定义;上面的**禁用词表是它的一个特例**(被误用会引发全篇返工的那些词)。
|
|
54
|
+
- **退出与降级**:做错了怎么退。
|
|
55
|
+
|
|
56
|
+
**调研 / 研究族**:骨架与执行归 `multi-perspective-research`(estimand、覆盖矩阵与关闭条件、渠道走查、矛盾图、未解清单、自评、多轮 program 节拍),本文件不重述。族间约束:调研结论被引入方案族文档时降为「依据」并附其证据状态,不得升格为方案的结论。
|
|
57
|
+
|
|
58
|
+
**现状 / 梳理族**:归 `requirement-baseline`。族间约束:现状与目标分成两份文档;目标文档首句写明「不代表当前生产能力」并指向现状文档。
|
|
59
|
+
|
|
60
|
+
**评审 / 发现族**:**去重前的原始发现进工作底稿**(去重、归并、定级都是加工,加工前的记录要留得住),按 §3 运作——该族最容易触发 §3 的**写入前置**,因为原始发现常含身份线索与凭据。结论面放**待裁决项**与**已裁决结果**(裁决、依据、责任人、下一步),不放未经核实的原始发现。
|
|
61
|
+
|
|
62
|
+
**计划 / 整改族**:先写**目标与范围**(这轮要达成什么、明确不含什么)、**依赖与前置**(谁挡着谁、外部依赖)、**风险与应对**;再是条目表,每条带 owner、阶段、完成判据——**没有完成判据的条目不进计划**。只有条目表而没有前三项的,是任务清单不是计划。
|
|
63
|
+
|
|
64
|
+
## §3 结论先行,证据归卷
|
|
65
|
+
|
|
66
|
+
**正文按结论先行组织**:顶层一个主论点(读者只记住一句话时记住的那句)→ 其下若干组支撑论点,同组之间尽量互斥、合起来回答上一层 → 证据在底层。组数**服从内容**:常见是 2–3 组,一组说明没有真正分组、组数过多说明还能再归并,但**不为凑数硬并或硬拆**——真有四个不可合并的风险域就写四组,只有一个足以承重的理由就写一组。分组不得挤掉任何一个已识别的关切(见 §5)。所谓「一页纸」是这个结构的**结果**,不是独立规则;页数不是判据,**能不能一句话说清主张、且每层都真的在支撑上一层**才是。
|
|
67
|
+
|
|
68
|
+
**证据与过程归到独立的一册(工作底稿),按**下表**运作——这些判据借自审计底稿的成文要求(见 §7),本文只借判据,不主张交付文档等同审计:
|
|
69
|
+
|
|
70
|
+
| 判据 | 含义 |
|
|
71
|
+
|---|---|
|
|
72
|
+
| 写入前置 | **先判敏感级,再决定要不要前置**:公开材料与非敏感的过程记录直接写入,无额外义务。**只有敏感 / 受控材料**才在复制之前定留存期、按最小必要裁剪(身份线索按需假名化并单独限权),**不能先全量落盘再回头治理**——第一份副本就已经形成暴露面。凭据与受控材料**不写入会被广泛分发的面**。**本文件到此为止**:收集是否合规、留存是否合法、发现问题后报给谁、要不要吊销或删除,都是安全 / 合规判断与运行态动作,归组织既有的安全与事件响应流程及 `feature-risk-router` 的安全评审闸;文档侧不自行认定违规、不自行吊销或删改既有材料,存疑时暂停扩大分发并交 owner |
|
|
73
|
+
| 收录标准 | **一个未参与本工作、有经验的同行,能据此册重建:做了什么、取到什么证据、如何得出结论**。够不够不由作者的感觉判,由这条判 |
|
|
74
|
+
| 归卷 | 证据册**限期归卷成册**(随交付定稿一并封版);归卷后不再随手增删,**事后的更正本身要留痕**(改了什么、为什么、谁改的),不覆盖原记录 |
|
|
75
|
+
| 保管 | 对**有权保留**的材料,处置是**受控保管**——保密、完整性、可取回三者同时成立——**而不是丢弃唯一证据**;给不了保管条件时暂停写入,把保管方案交由风险 / 数据 owner 决定,作者不自行开通存储或变更权限。留存期限与删除义务(法定、合同、当事人要求)由该 owner 与组织合规流程裁定,本文件不代判 |
|
|
76
|
+
|
|
77
|
+
**访问面由内容决定,不由册名决定**(按册名列清单必然漏):任何一册装了什么就按什么定分发面,正文与摘要页同样受此约束,敏感内容不因为「这是给决策者看的那页」而获得更宽的分发面。凭据类按上表「写入前置」处置(绝不为「保留原始」在册中留下可用凭据);正文中指向受控册的**指针本身也受此约束**——只写既不泄露内容、也不构成访问凭据的指针(受控系统内的记录号、保管人与申请流程),不写直链、带访问参数的 URL、或路径与标题本身即透露内容的定位。**可回查不等于可传播,定位不等于可访问。**
|
|
78
|
+
|
|
79
|
+
分成几册由内容与读者决定,常见落点是:正文(结论·约束·动作)、工作底稿(证据与过程)、细则(某一层的实施步骤)、明细(逐条发现或定量明细)。**分册规则要在首稿就写下来**,否则「这段该不该进正文」每轮都要重吵一次——这是反复润色的主要来源之一。分册是目标形态的描述,动手改已存在的文档集仍按开头的全局边界。
|
|
80
|
+
|
|
81
|
+
## §4 表示形式随族定
|
|
82
|
+
|
|
83
|
+
**下表列的是候选,不是必备清单。** 画哪几张由**要承载的主张**决定——有部署差异才画部署图,有跨组件时序才画时序图,没有就不画;缺某张图**不构成形态不合规**。硬约束一列约束的是**画了的图必须怎样**,不是必须画什么。
|
|
84
|
+
|
|
85
|
+
| 族 | 主形态 | 硬约束 |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| 方案 / 架构 | 分层图(上下文 → 容器 → 组件)、部署拓扑、时序、数据流 | **一张图一个抽象层,不混层**;每层对应一类受众 |
|
|
88
|
+
| 调研 | 常见落点:证据集形成流程图(识别 / 筛除及其理由与计数)、关系结构图、分布定位图 | 是否需要图、需要哪几张由 `multi-perspective-research` 裁定;本表只提供候选,不据此判该族文档不合规 |
|
|
89
|
+
| 现状 / 梳理 | 缺口表;主张涉及规模 / 趋势时再加定量明细与仪表盘 | 每格可追到取证时点;定性盘点不必凑定量件 |
|
|
90
|
+
| 评审 | 结论面(待裁决项 + 已裁决结果)、明细 | 结论面不放**未经核实**的原始发现——后者进工作底稿,按 §3 运作 |
|
|
91
|
+
| 计划 / 整改 | 阶段甘特或里程碑表、依赖关系图 | 每条可认领:有 owner、阶段与完成判据;没有完成判据的条目不上图 |
|
|
92
|
+
|
|
93
|
+
图的**承载位置与格式**(原生画板 / 图片 / 源文件加导出件)在首稿一并定死;多载体时的载体登记与同步义务归 `multi-perspective-research` 的多轮 program 节。**同批一并冻结版式契约**(画布比例、字号阶梯、色 token 及其对比度、单格文本上限、分组单元)——一致性是外部要求,冻结成哪几档是团队自选,契约缺失则一致性不可判定。
|
|
94
|
+
|
|
95
|
+
**这张表定「画哪几张」,不定「画成什么样」**:图种由主张形态推出(有无显式事件触发)、画了必须满足的记法硬约束、调研族图上实体的回指要求、版式契约与目标端渲染保真,见同目录 `figure-and-table-craft.md`。
|
|
96
|
+
|
|
97
|
+
## §5 可判定的验收(替代「写得好不好」)
|
|
98
|
+
|
|
99
|
+
- (§5 的验收面向**本文件持有的族**;调研与现状族按其 owner 的完成标准判。)
|
|
100
|
+
- **关切覆盖**:列出干系人与各自关切,**每个关切至少被一个视图或章节回答**——架构描述标准的核心一致性要求,也是最容易机械查的完整性判据。
|
|
101
|
+
- **断言可裁决**:每条载重结论的证据状态显式(来源陈述 / 推论 / 作者判断);分级口径归 `tighten-doc`。
|
|
102
|
+
- **开放项显式**:未关闭项的数量与其阻塞对象可数。
|
|
103
|
+
- **动作可认领**:每条动作有 owner、阶段与完成判据(三者缺一即不可认领)。
|
|
104
|
+
- **表示形式合规**:**已经画出来的图**逐张过 §4 的硬约束(是否混层、是否回答了它该回答的问题);**不以「少了哪张图」判不合规**。调研与现状族的完整性仍按其 owner 的完成标准判。**图级验收测试**:这张图能否脱离正文被独立看懂——把图单独给没读过正文的人,他能否说出图在主张什么;不能就是图没画完。可机械判定的部分(对比度、文本溢出、图例与连线标签缺失、分组、契约偏离、表格真表头、载体错配、图文引用一致)由 `../scripts/figure-lint.py` 与 `../scripts/doc-lint.py` 挡,判据与其档位见 `figure-and-table-craft.md`;检查器本身按该文件 §8 先自测能报失败再信其绿。
|
|
105
|
+
|
|
106
|
+
## §6 修订与润色不是一件事
|
|
107
|
+
|
|
108
|
+
全局修订(命题、结构、证据、分册)先于局部润色(措辞、格式),顺序不可倒。**在命题或分册未定时做的润色轮,会被下一次结构变更整段推翻**——它记在账上是「润色轮」,实际是修订轮。这是「几乎每份文档都要反复润色」最常见的机制。判据:本轮在改「说什么」还是「怎么说」;只要还在改「说什么」,就不进润色。
|
|
109
|
+
|
|
110
|
+
首稿前锁定读者 / 用途 / 载体 / 篇幅预算的 doc charter 见同目录 `doc-charter-first.md`;本文件是那张 charter 表里 **Genre** 一格的展开。
|
|
111
|
+
|
|
112
|
+
## §7 外部来源
|
|
113
|
+
|
|
114
|
+
- **Malte Ubl**, "Design Docs at Google" — <https://www.industrialempathy.com/posts/design-docs-at-google/>— goals + **non-goals**、**alternatives considered 及未选原因**列为设计文档骨架必备节
|
|
115
|
+
- **Michael Nygard**, "Documenting Architecture Decisions"(2011-11-15)— <https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions>— 单个决定的记录格式;本文件不重述,归 `product-rd-workflow` 的 adr-convention 参考
|
|
116
|
+
- **公开 RFC 提案模板** — <https://github.com/rust-lang/rfcs/blob/master/0000-template.md>;Prior art 一节由 RFC 2333 补入 <https://rust-lang.github.io/rfcs/2333-prior-art.html>— motivation / drawbacks / rationale and alternatives / prior art / unresolved questions;本文件据此补入「本方案自身的代价」与「外部先例」两项必答节
|
|
117
|
+
- **ISO/IEC/IEEE 42010** Architecture description(2nd ed. 2022)— 概念模型 <https://www.iso-architecture.org/42010/cm/>— 干系人 / 关切 / 视角 / 视图;一致性要求为每个被识别的关切至少被一个视角框定
|
|
118
|
+
- **arc42** 架构文档模板 — <https://arc42.org/overview/>(12 节:引言与目标 / 约束 / 上下文与范围 / 解决方案策略 / 构件视图 / 运行时视图 / 部署视图 / 横切概念 / 架构决策 / 质量需求 / 风险与技术债 / 术语表)— 本文件 §2 的必答项按它做过交叉校验,据此补入「质量目标与验收场景」「术语与口径表」两项;本文件不搬它的 12 节编号(那是模板,不是最小必答集)
|
|
119
|
+
- **C4 model**(Simon Brown)— <https://c4model.com/>— context / container / component / code 四层,notation-independent,每层对应不同受众
|
|
120
|
+
- **PRISMA 2020 + PRISMA-S** — 声明原文 <https://pmc.ncbi.nlm.nih.gov/articles/PMC8008539/> — 检索式可复现、排除计数与理由、证据集形成流程图
|
|
121
|
+
- **ICH E9(R1)** Addendum on estimands and sensitivity analysis(ICH 官方指导原则,按标准号可查)— estimand 五属性(population / treatment / endpoint / intercurrent events / population-level summary),「先定测什么再测」的成文来源
|
|
122
|
+
- **Barbara Minto**(<https://www.barbaraminto.com/>), *The Pyramid Principle: Logic in Writing and Thinking*(1985;1996 修订版《The Minto Pyramid Principle》)— 结论先行:顶层主论点 + 分组支撑 + 底层证据;本文件据此把「一页纸」还原为结构的结果而非页数规则
|
|
123
|
+
- **ISA 230** Audit Documentation(IAASB 国际审计准则,按标准号可查)— 「未参与该工作的有经验同行可据此重建工作、证据与结论」的收录判据;限期归卷、归卷后不删弃且更正留痕;保密 / 完整性 / 可取回的保管要求。本文件只借这三条判据用于交付文档的证据册,不主张交付文档等同审计底稿,也不搬其法定留存年限(留存期按各自司法辖区与公司政策定)
|
|
124
|
+
- 写作教学中一致的 revision / editing 区分(多所高校写作中心)— 全局修订先于局部润色
|
|
125
|
+
|
|
126
|
+
## §8 故意不借鉴
|
|
127
|
+
|
|
128
|
+
| 概念 | 原因 |
|
|
129
|
+
|---|---|
|
|
130
|
+
| 固定页数上限(如「六页备忘录」「一页纸」当规则用) | 页数是某组织的会议口径,换组织不成立;本文件取其**结构**判据(§3 结论先行)与篇幅预算(归同目录 `doc-charter-first.md`),不搬数字 |
|
|
131
|
+
| Diátaxis 四模式直接套交付文档 | 它面向产品 / API 文档的**使用者**模式;交付型方案与调研文档的读者是决策者,不是使用者。只借「先判模式再定骨架」这一层 |
|
|
132
|
+
| 把 ADR 模板当方案文档骨架 | ADR 记一个决定;方案文档承载一组决定加实施路径,粒度不同 |
|
|
133
|
+
| 把 42010 全套视角规范搬进模板 | 该标准面向体系化架构描述;此处只取「关切—视图必须一一有着落」这条可判定要求 |
|
|
@@ -8,10 +8,12 @@ For a multi-round deliverable doc (several revision rounds with the reader-owner
|
|
|
8
8
|
| Purpose | What should the reader be able to do or decide after reading? |
|
|
9
9
|
| Venue | Presented (talk outline: one figure + one claim per section) vs self-read (narrative entry page)? Collaborative platform vs repo file? |
|
|
10
10
|
| Length budget | A hard cap for the entry surface; overflow goes to child pages/appendices, the entry gains only a navigation line. |
|
|
11
|
+
| Genre | Which genre leads here? A doc may sit on both axes at once — a delivery genre (方案/架构, 调研, 现状梳理, 评审, 计划) and a user-facing documentation mode (tutorial / how-to / reference / explanation); record the leading one, and let §0 of the linked file settle precedence rather than forcing an either/or. The genre drives the first-draft section list and the 正文/证据 split, and narrows which diagram forms are candidates — it never mandates a fixed set of diagrams. `deliverable-doc-genre-skeletons.md` owns genre classification, the cross-genre form rules, and the 方案/架构 skeleton, and routes 调研/现状 to their own owners; take all of that from there rather than restating it here (调研 executes under `multi-perspective-research`, 现状 under `requirement-baseline`). |
|
|
11
12
|
|
|
12
13
|
Rules:
|
|
13
14
|
|
|
14
15
|
- **Classify each mid-stream ask against the charter instead of appending reactively.** A new request is either in-charter (edit in place), a charter change (re-confirm the charter first, then restructure once), or out-of-scope (park it). Appending every ask as a new section is how a deliverable doc accretes into an unreadable monolith.
|
|
15
16
|
- **A second direction-level correction within one doc effort is the charter-not-locked signal**: stop drafting, lock the charter with the reader-owner (one short structured question), then restructure once against it. Continuing to patch per-correction after that signal produces compliant-but-shapeless output — the same failure class as the premise-rejection guard in `SKILL.md`, one level earlier.
|
|
17
|
+
- **Global revision precedes local polish; the order is not reversible.** 判据是本轮在改「说什么」(命题、结构、证据、分册归属)还是「怎么说」(措辞、格式)——只要还在改前者,就不进润色轮:命题或分册未定时做的润色会被下一次结构变更整段推翻,账上记成润色轮,实际是修订轮。这也是 charter 与 Genre 两格必须先锁的原因。**反过来不成立:润色本身就是多轮收敛的,反复润色不等于实质未定。**一致性与口径漂移、跨节重复、密块、元语自证等是**逐位置**缺陷,每一遍改动都可能重新引入前一遍已清掉的类;类目、判法与多轮节拍归 `SKILL.md`(DELETE / FORM / closeout),此处不复述。判据是**实质的状态**,不是本轮请求的措辞:命题 / 结构 / 分册归属尚未定 → 仍不进润色轮,回 charter/Genre(即使本轮只被要求改措辞);实质已定而同类缺陷仍有残留 → 那是执行覆盖问题,按 closeout 补,不因为「又要润色一遍」退回 charter。
|
|
16
18
|
- The charter is a drafting gate, not a substance owner: substantive decisions still come from the user or the owning skill; the charter only fixes who/what/where/how-long so later asks can be classified.
|
|
17
19
|
- Without a budget, growth restraint does not survive multi-round pressure — set the length budget at charter time and enforce it at each round's closeout, splitting overflow to child pages instead of raising the cap. Splitting stays inside the doc-set authority rule in `SKILL.md`: for a no-owner deliverable doc the reader-owner agrees the split (structure decision, not self-authorized); for spec/standards/guideline families the doc set is owner-settled — flag a split candidate, do not split.
|