@ccoalm/ccl-skills 0.1.0 → 0.2.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/test_init_policy_matrix.sh +93 -16
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_parse_probe_result.sh +10 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate.sh +249 -5
- package/dist/assets/marketplace/plugins/ccl-skills/skills/code-review/scripts/test_review_gate_abort_leak.sh +394 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/architecture-playbook.md +2 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/go-microservice-architecture/references/cross-cutting-concerns.md +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/SKILL.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-capability-composition.md +128 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-command-sandbox.md +35 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-session-persistence.md +54 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/agent-tool-dispatch.md +11 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/llm-inference-integration/references/model-prompt-evaluation.md +7 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/platform-release-engineering/references/canary-and-rollout-strategy.md +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/external-ui-ux-quality-benchmarks.md +50 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/product-ui-ux-design/references/ui-ux-audit.md +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/architecture-playbook.md +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/python-service-architecture/references/packaging-runtime-readiness.md +6 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/SKILL.md +1 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/external-practice-controls.md +59 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/harness-patterns-and-eval.md +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/rule-consolidation.md +3 -1
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-register.md +43 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/references/source-to-skill-extraction.md +16 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/impact-chain-gate.rb +391 -14
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/register-firing-path-resolution.rb +74 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_regressions.sh +74 -33
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_check_ccl_skill_catalog.sh +11 -4
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_gate_verdict_differential.sh +421 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_round_attribution.sh +576 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_impact_chain_source_refuted.sh +176 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_regression_runner_lanes.sh +101 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/skill-extraction-workflow/scripts/test_validate_skill_root_depth.sh +6 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/SKILL.md +2 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/ci-fixtures-and-flake-control.md +19 -2
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/e2e-real-flow-testing.md +1 -0
- package/dist/assets/marketplace/plugins/ccl-skills/skills/testing-strategy/references/test-code-authoring-patterns.md +3 -3
- package/dist/assets/release.json +63 -33
- package/package.json +1 -1
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# RED-baseline probes for the impact-chain gate's ROW-OWNERSHIP ATTRIBUTION.
|
|
3
|
+
#
|
|
4
|
+
# Three forms were recorded separately across the 034 batches and registered as
|
|
5
|
+
# one deferred hardening item. Reproduction against the current baseline split
|
|
6
|
+
# them into two independent roots, and only one is fixed here.
|
|
7
|
+
#
|
|
8
|
+
# Leg 0 CONTROL one owner change, one well-formed row: must be green.
|
|
9
|
+
# Leg A form 1 an owner restored to base bytes leaves the changed set,
|
|
10
|
+
# and its surviving row kept vouching for a change the
|
|
11
|
+
# delivered diff no longer contains.
|
|
12
|
+
# Leg B form 2 a row citing a path inside the owner package but never
|
|
13
|
+
# its SKILL.md resolved to nothing, so the declaration it
|
|
14
|
+
# makes was never evaluated.
|
|
15
|
+
# Leg H REGRESSION the register carries other five-column tables; widening
|
|
16
|
+
# resolution must not drag them into this gate.
|
|
17
|
+
#
|
|
18
|
+
# FORM 3 IS NOT FIXED HERE, BY DECISION. A stacked branch that integrates its
|
|
19
|
+
# upstream branch by merge is still refused a row it cannot supply; the standing
|
|
20
|
+
# workaround is to integrate by rebase, which is already the documented practice.
|
|
21
|
+
# The suppression that would have fixed it was implemented and then removed: it
|
|
22
|
+
# necessarily proxies "this round authored nothing of its own" with a textual
|
|
23
|
+
# comparison, and three adversarial review rounds found eight ways through that
|
|
24
|
+
# proxy (deletion, relocation, duplication, partial import, dropped import,
|
|
25
|
+
# rejected removal, duplicate-line cancellation, and binary/mode invisibility).
|
|
26
|
+
# Same class three rounds running is the repo's own signal to question the
|
|
27
|
+
# capability rather than patch it again, and the risk is asymmetric: form 3 costs
|
|
28
|
+
# an author one rebase, while a leaky suppression silently accepts undeclared
|
|
29
|
+
# owner changes — the very failure the two forms above are about. The risk owner
|
|
30
|
+
# chose deletion. Reinstating it needs an invariant, not another proxy.
|
|
31
|
+
#
|
|
32
|
+
# Each leg asserts the DESIRED behavior, and every leg expecting a refusal also
|
|
33
|
+
# asserts WHICH refusal. rc alone is a weak oracle: a leg red for a fixture
|
|
34
|
+
# defect looks identical to the form reproducing, and both directions of that
|
|
35
|
+
# mistake were observed while writing this file. Do not "fix" a leg by relaxing
|
|
36
|
+
# its assertion.
|
|
37
|
+
set -euo pipefail
|
|
38
|
+
|
|
39
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
|
40
|
+
# REVERSE DIFFERENTIAL. Each leg below states which gate behavior it pins, and a
|
|
41
|
+
# leg only means something if the gate it replaces fails it. Point this at the
|
|
42
|
+
# older gate to check that:
|
|
43
|
+
#
|
|
44
|
+
# git show <ref>:skills/skill-extraction-workflow/scripts/impact-chain-gate.rb > /tmp/old.rb
|
|
45
|
+
# IMPACT_CHAIN_GATE=/tmp/old.rb bash "$0"
|
|
46
|
+
#
|
|
47
|
+
# The legs marked as differential must go RED there. Without the override this
|
|
48
|
+
# runs the working-tree gate, which is the ordinary regression direction; the
|
|
49
|
+
# override is what makes the reverse direction reproducible instead of a claim
|
|
50
|
+
# about a run nobody else can repeat.
|
|
51
|
+
GATE="${IMPACT_CHAIN_GATE:-$SCRIPT_DIR/impact-chain-gate.rb}"
|
|
52
|
+
[ -f "$GATE" ] || { echo "FAIL: gate not found: $GATE" >&2; exit 1; }
|
|
53
|
+
|
|
54
|
+
TMP="$(mktemp -d "${TMPDIR:-/tmp}/icattr.XXXXXX")"
|
|
55
|
+
trap 'rc=$?; rm -rf "$TMP"; exit $rc' EXIT
|
|
56
|
+
|
|
57
|
+
fail() { echo "FAIL: $*" >&2; exit 1; }
|
|
58
|
+
note() { echo " $*"; }
|
|
59
|
+
|
|
60
|
+
LEDGER_REL="skills/skill-extraction-workflow/references/source-register.md"
|
|
61
|
+
|
|
62
|
+
# One curated upstream owner package plus the ledger header. The owner body
|
|
63
|
+
# carries a numbered normative rule line so a firing-path anchor can resolve to
|
|
64
|
+
# a genuinely changed rule rather than to prose.
|
|
65
|
+
seed_repo() { # <repo-dir>
|
|
66
|
+
local repo="$1"
|
|
67
|
+
mkdir -p "$repo"
|
|
68
|
+
git -C "$repo" init -q -b trunk
|
|
69
|
+
git -C "$repo" config user.email test@example.invalid
|
|
70
|
+
git -C "$repo" config user.name "Test User"
|
|
71
|
+
git -C "$repo" config commit.gpgsign false
|
|
72
|
+
mkdir -p "$repo/skills/product-rd-workflow" \
|
|
73
|
+
"$repo/skills/testing-strategy" \
|
|
74
|
+
"$repo/skills/skill-extraction-workflow/references"
|
|
75
|
+
cat > "$repo/skills/product-rd-workflow/SKILL.md" <<'MD'
|
|
76
|
+
---
|
|
77
|
+
name: product-rd-workflow
|
|
78
|
+
description: Fixture routing description for the attribution differential.
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
# Fixture Owner
|
|
82
|
+
|
|
83
|
+
## Rules
|
|
84
|
+
|
|
85
|
+
- Baseline rule line that the case commits mutate.
|
|
86
|
+
MD
|
|
87
|
+
cat > "$repo/skills/testing-strategy/SKILL.md" <<'MD'
|
|
88
|
+
---
|
|
89
|
+
name: testing-strategy
|
|
90
|
+
description: Second fixture owner, used by the upstream-branch round.
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
# Second Fixture Owner
|
|
94
|
+
|
|
95
|
+
## Rules
|
|
96
|
+
|
|
97
|
+
- Baseline rule line owned by the upstream integration branch.
|
|
98
|
+
MD
|
|
99
|
+
printf '| Lesson | Downstream owner | Behavior | Status | Evidence |\n| --- | --- | --- | --- | --- |\n' \
|
|
100
|
+
> "$repo/$LEDGER_REL"
|
|
101
|
+
git -C "$repo" add -A
|
|
102
|
+
git -C "$repo" commit -qm "seed fixture base"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
# The owner mutation and the row's firing path are a matched pair. The gate
|
|
106
|
+
# resolves a file locator by finding the anchor as a substring of an ADDED line
|
|
107
|
+
# in the row's own round diff, requiring that line to be a list item carrying
|
|
108
|
+
# normative-action vocabulary. So the rule line must be a real `- ... must ...`
|
|
109
|
+
# rule and the anchor must be a token unique to it.
|
|
110
|
+
rule_anchor() { printf 'ATTRIBUTION-FIXTURE-%s' "$1"; }
|
|
111
|
+
|
|
112
|
+
mutate_owner_rule() { # <repo-dir> <owner-slug> <marker>
|
|
113
|
+
local repo="$1" owner="$2" marker="$3"
|
|
114
|
+
printf -- '- Rule %s must be recorded before the round lands.\n' "$(rule_anchor "$marker")" \
|
|
115
|
+
>> "$repo/skills/$owner/SKILL.md"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# A complete, well-formed row: valid status, full behavioral-evidence
|
|
119
|
+
# declaration, owner-scoped firing path that resolves to the rule line the
|
|
120
|
+
# matching mutate_owner_rule added, and the owner key in the evidence cell.
|
|
121
|
+
append_valid_row() { # <repo-dir> <owner-slug> <marker> <lesson>
|
|
122
|
+
local repo="$1" owner="$2" marker="$3" lesson="$4"
|
|
123
|
+
printf '| %s | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/%s/SKILL.md#%s | `updated` | `%s/SKILL.md` fixture change |\n' \
|
|
124
|
+
"$lesson" "$owner" "$(rule_anchor "$marker")" "$owner" >> "$repo/$LEDGER_REL"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
run_gate() { # <repo-dir> <base-ref> -> sets rc, out
|
|
128
|
+
set +e
|
|
129
|
+
out="$(env -u ALIAS_AUDIT_CMD CCL_SKILL_BASE_REF="$2" ruby "$GATE" "$1" 2>&1)"
|
|
130
|
+
rc=$?
|
|
131
|
+
set -e
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
legs_failed=0
|
|
135
|
+
# <leg-name> <expected-rc> <form-summary> [expected-token]
|
|
136
|
+
# The token is the attribution guard. rc alone is a weak oracle here: a refusal
|
|
137
|
+
# for an unrelated reason (a fixture defect, a broken anchor) is still rc=1 and
|
|
138
|
+
# would read as the form being closed. When a leg expects a refusal it must
|
|
139
|
+
# also name WHICH refusal, so a green leg means the intended predicate fired.
|
|
140
|
+
report_leg() {
|
|
141
|
+
if [ "$rc" != "$2" ]; then
|
|
142
|
+
echo " $1: RED (rc=$rc, want $2) — $3 REPRODUCES"
|
|
143
|
+
note "gate output:"
|
|
144
|
+
printf '%s\n' "$out" | sed 's/^/ | /'
|
|
145
|
+
legs_failed=$((legs_failed + 1))
|
|
146
|
+
return
|
|
147
|
+
fi
|
|
148
|
+
if [ -n "${4:-}" ]; then
|
|
149
|
+
case "$out" in
|
|
150
|
+
*"$4"*) : ;;
|
|
151
|
+
*)
|
|
152
|
+
echo " $1: RED (rc=$rc as wanted, but the wrong refusal) — expected $4"
|
|
153
|
+
note "gate output:"
|
|
154
|
+
printf '%s\n' "$out" | sed 's/^/ | /'
|
|
155
|
+
legs_failed=$((legs_failed + 1))
|
|
156
|
+
return
|
|
157
|
+
;;
|
|
158
|
+
esac
|
|
159
|
+
fi
|
|
160
|
+
echo " $1: PASS (rc=$rc) — $3 does not reproduce on this baseline"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
echo "test_impact_chain_round_attribution: row-ownership attribution"
|
|
164
|
+
|
|
165
|
+
# ---------------------------------------------------------------------------
|
|
166
|
+
# Leg 0 — CONTROL. The plain shape every leg below is a variation of: one owner
|
|
167
|
+
# change, one well-formed row declaring it. This must be GREEN. Without this
|
|
168
|
+
# control a fixture defect (an anchor that does not resolve, a malformed row)
|
|
169
|
+
# reads as the form reproducing, and a leg that is red for the wrong reason
|
|
170
|
+
# reads as the form being closed. Both directions were observed while writing
|
|
171
|
+
# this file, so the control is load-bearing, not ceremony.
|
|
172
|
+
# ---------------------------------------------------------------------------
|
|
173
|
+
Z="$TMP/leg-0"
|
|
174
|
+
seed_repo "$Z"
|
|
175
|
+
git -C "$Z" branch fixture-base HEAD
|
|
176
|
+
git -C "$Z" switch -q -c case-control
|
|
177
|
+
mutate_owner_rule "$Z" product-rd-workflow Z
|
|
178
|
+
append_valid_row "$Z" product-rd-workflow Z "Fixture control row"
|
|
179
|
+
git -C "$Z" add -A
|
|
180
|
+
git -C "$Z" commit -qm "round 1: change the owner and declare it"
|
|
181
|
+
run_gate "$Z" fixture-base
|
|
182
|
+
if [ "$rc" != 0 ]; then
|
|
183
|
+
echo " leg 0 (control): BROKEN FIXTURE (rc=$rc, want 0)"
|
|
184
|
+
printf '%s\n' "$out" | sed 's/^/ | /'
|
|
185
|
+
fail "the control shape is not green, so no other leg's verdict means anything"
|
|
186
|
+
fi
|
|
187
|
+
echo " leg 0 (control): PASS (rc=0) — the fixture shape itself is green"
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# ---------------------------------------------------------------------------
|
|
191
|
+
# Leg A — form 1: owner restored to base, row stays green (FALSE-GREEN)
|
|
192
|
+
# ---------------------------------------------------------------------------
|
|
193
|
+
A="$TMP/leg-a"
|
|
194
|
+
seed_repo "$A"
|
|
195
|
+
git -C "$A" branch fixture-base HEAD
|
|
196
|
+
git -C "$A" switch -q -c case-restore
|
|
197
|
+
mutate_owner_rule "$A" product-rd-workflow "A"
|
|
198
|
+
append_valid_row "$A" product-rd-workflow A "Fixture restored-owner row"
|
|
199
|
+
git -C "$A" add -A
|
|
200
|
+
git -C "$A" commit -qm "round 1: change the owner and declare it"
|
|
201
|
+
# The restore: exactly what a rebase/conflict resolution that takes the base
|
|
202
|
+
# side does. The ledger row is untouched and still reads as a live declaration.
|
|
203
|
+
git -C "$A" checkout -q fixture-base -- skills/product-rd-workflow/SKILL.md
|
|
204
|
+
git -C "$A" commit -qm "owner restored to base bytes (rebase/conflict restore)" -q
|
|
205
|
+
# Guard: the delivered diff really contains no owner change any more.
|
|
206
|
+
if git -C "$A" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/'; then
|
|
207
|
+
fail "leg A fixture is a no-op: the owner is still changed at HEAD"
|
|
208
|
+
fi
|
|
209
|
+
git -C "$A" diff --name-only fixture-base HEAD | grep -qx "$LEDGER_REL" \
|
|
210
|
+
|| fail "leg A fixture is a no-op: the ledger row did not survive"
|
|
211
|
+
run_gate "$A" fixture-base
|
|
212
|
+
report_leg "leg A (owner restored to base)" 1 "form 1" "impact_chain_row_vouches_for_unchanged_owner"
|
|
213
|
+
|
|
214
|
+
# ---------------------------------------------------------------------------
|
|
215
|
+
# Leg B — form 2: row without a recognized owner key is never evaluated
|
|
216
|
+
# ---------------------------------------------------------------------------
|
|
217
|
+
B="$TMP/leg-b"
|
|
218
|
+
seed_repo "$B"
|
|
219
|
+
git -C "$B" branch fixture-base HEAD
|
|
220
|
+
git -C "$B" switch -q -c case-unkeyed
|
|
221
|
+
mutate_owner_rule "$B" product-rd-workflow "B"
|
|
222
|
+
# Row 1 binds the owner and satisfies the per-round demand.
|
|
223
|
+
append_valid_row "$B" product-rd-workflow B "Fixture binding row"
|
|
224
|
+
# Row 2 is deliberately INVALID where the gate checks bound rows: the
|
|
225
|
+
# behavioral-evidence declaration is truncated (no observed-failure, no
|
|
226
|
+
# firing-path) and the evidence cell names only a references/ path, never the
|
|
227
|
+
# owning SKILL.md key. If the gate evaluates every added row, this must be
|
|
228
|
+
# rejected. If it only ever evaluates rows it managed to bind, this row is
|
|
229
|
+
# silently inert.
|
|
230
|
+
printf '| Fixture unkeyed row | `downstream-executor` | behavioral-evidence: RED-baseline | `updated` | skills/product-rd-workflow/references/nonexistent-note.md supporting note only |\n' \
|
|
231
|
+
>> "$B/$LEDGER_REL"
|
|
232
|
+
git -C "$B" add -A
|
|
233
|
+
git -C "$B" commit -qm "round 1: one binding row plus one unkeyed incomplete row"
|
|
234
|
+
run_gate "$B" fixture-base
|
|
235
|
+
report_leg "leg B (unkeyed row never evaluated)" 1 "form 2" "impact_chain_firing_path_missing"
|
|
236
|
+
|
|
237
|
+
# ---------------------------------------------------------------------------
|
|
238
|
+
# Leg H — UNRELATED TABLE regression. The register carries other five-column
|
|
239
|
+
# tables whose rows have a status word and can cite a path inside an owner
|
|
240
|
+
# package. Before prefix resolution they never matched an exact
|
|
241
|
+
# `<owner>/SKILL.md` and were skipped; that prior behavior must survive, or the
|
|
242
|
+
# widening silently drags unrelated bookkeeping into this gate. The row here
|
|
243
|
+
# cites a curated owner's reference path and carries NO behavioral-evidence
|
|
244
|
+
# declaration, which is the discriminator that keeps it out.
|
|
245
|
+
# ---------------------------------------------------------------------------
|
|
246
|
+
H="$TMP/leg-h"
|
|
247
|
+
seed_repo "$H"
|
|
248
|
+
git -C "$H" branch fixture-base HEAD
|
|
249
|
+
git -C "$H" switch -q -c case-unrelated
|
|
250
|
+
printf '| Note | Owner | Rationale | Status | Reference |\n| --- | --- | --- | --- | --- |\n| Fixture unrelated bookkeeping row | `some-reviewer` | Recorded for traceability, no impact-chain claim | `routed` | see skills/product-rd-workflow/references/relocated-note.md for the rationale |\n' \
|
|
251
|
+
>> "$H/$LEDGER_REL"
|
|
252
|
+
git -C "$H" add -A
|
|
253
|
+
git -C "$H" commit -qm "round 1: append a row belonging to a different register table"
|
|
254
|
+
# Guard: the row really would resolve to a selected owner on a path-only rule.
|
|
255
|
+
git -C "$H" show "HEAD:$LEDGER_REL" | grep -q 'skills/product-rd-workflow/references/relocated-note.md' \
|
|
256
|
+
|| fail "leg H fixture is a no-op: the unrelated row lost its owner-package path"
|
|
257
|
+
run_gate "$H" fixture-base
|
|
258
|
+
report_leg "leg H (unrelated five-column table row)" 0 "the unrelated-table regression"
|
|
259
|
+
|
|
260
|
+
# ---------------------------------------------------------------------------
|
|
261
|
+
# Leg L — MULTI-OWNER blocking. Resolving to more than one selected owner used
|
|
262
|
+
# to warn and drop the row, which is the worst pairing: the author sees a
|
|
263
|
+
# warning, the row is never evaluated, and the exit code says the gate passed.
|
|
264
|
+
# Without a leg here a regression back to warn-and-drop leaves every other leg
|
|
265
|
+
# green while an explicit acceptance requirement fails.
|
|
266
|
+
# ---------------------------------------------------------------------------
|
|
267
|
+
L="$TMP/leg-l"
|
|
268
|
+
seed_repo "$L"
|
|
269
|
+
git -C "$L" branch fixture-base HEAD
|
|
270
|
+
git -C "$L" switch -q -c case-ambiguous
|
|
271
|
+
mutate_owner_rule "$L" product-rd-workflow L
|
|
272
|
+
mutate_owner_rule "$L" testing-strategy L2
|
|
273
|
+
# Both owners are separately and validly declared, so the ONLY thing left for
|
|
274
|
+
# the gate to object to is the ambiguous row. Without these two the round would
|
|
275
|
+
# fail for a missing declaration instead, and the leg would pass against a gate
|
|
276
|
+
# that still merely warns — which is exactly what it must detect.
|
|
277
|
+
append_valid_row "$L" product-rd-workflow L "Fixture first owner row"
|
|
278
|
+
append_valid_row "$L" testing-strategy L2 "Fixture second owner row"
|
|
279
|
+
printf '| Fixture ambiguous row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | `product-rd-workflow/SKILL.md` and `testing-strategy/SKILL.md` both changed and are cited in one row |\n' \
|
|
280
|
+
"$(rule_anchor L)" >> "$L/$LEDGER_REL"
|
|
281
|
+
git -C "$L" add -A
|
|
282
|
+
git -C "$L" commit -qm "round 1: one row citing two changed selected owners"
|
|
283
|
+
run_gate "$L" fixture-base
|
|
284
|
+
report_leg "leg L (row resolving to two selected owners)" 1 "the multi-owner warn-and-drop" "impact_chain_row_ambiguous"
|
|
285
|
+
|
|
286
|
+
# ---------------------------------------------------------------------------
|
|
287
|
+
# Leg M — NON-CURATED owner. A row about a skill outside the curated upstream
|
|
288
|
+
# list is outside this gate's jurisdiction and must stay skipped, declaration or
|
|
289
|
+
# not. This is the acceptance requirement that the widening must not start
|
|
290
|
+
# selecting owners the curated list never picked.
|
|
291
|
+
# ---------------------------------------------------------------------------
|
|
292
|
+
M="$TMP/leg-m"
|
|
293
|
+
seed_repo "$M"
|
|
294
|
+
mkdir -p "$M/skills/worktree-isolation"
|
|
295
|
+
cat > "$M/skills/worktree-isolation/SKILL.md" <<'MD'
|
|
296
|
+
---
|
|
297
|
+
name: worktree-isolation
|
|
298
|
+
description: A fixture skill deliberately outside the curated upstream-owner list.
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
# Non-curated Fixture Owner
|
|
302
|
+
|
|
303
|
+
## Rules
|
|
304
|
+
|
|
305
|
+
- Baseline rule line owned by a skill this gate does not govern.
|
|
306
|
+
MD
|
|
307
|
+
git -C "$M" add -A
|
|
308
|
+
git -C "$M" commit -qm "seed a non-curated owner package"
|
|
309
|
+
git -C "$M" branch fixture-base HEAD
|
|
310
|
+
git -C "$M" switch -q -c case-noncurated
|
|
311
|
+
printf -- '- Rule %s must be recorded before the round lands.\n' "$(rule_anchor M)" \
|
|
312
|
+
>> "$M/skills/worktree-isolation/SKILL.md"
|
|
313
|
+
printf '| Fixture non-curated row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/worktree-isolation/SKILL.md#%s | `updated` | `worktree-isolation/SKILL.md` changed; this skill is not a curated upstream owner |\n' \
|
|
314
|
+
"$(rule_anchor M)" >> "$M/$LEDGER_REL"
|
|
315
|
+
git -C "$M" add -A
|
|
316
|
+
git -C "$M" commit -qm "round 1: change a non-curated owner and record it"
|
|
317
|
+
run_gate "$M" fixture-base
|
|
318
|
+
report_leg "leg M (non-curated owner stays out of scope)" 0 "the curated-list bypass"
|
|
319
|
+
|
|
320
|
+
# ---------------------------------------------------------------------------
|
|
321
|
+
# Leg N — MULTI-OWNER, NO DECLARATION. Leg L pins that a declaring row citing two
|
|
322
|
+
# selected owners blocks. This pins the other side: an unrelated register row
|
|
323
|
+
# that happens to mention two curated owners in prose asserts nothing this gate
|
|
324
|
+
# owns, so promoting its old warning to a merge block would be the same
|
|
325
|
+
# unrelated-table regression leg H guards. The two legs together are what make
|
|
326
|
+
# the blocking change scoped rather than blanket.
|
|
327
|
+
# ---------------------------------------------------------------------------
|
|
328
|
+
N="$TMP/leg-n"
|
|
329
|
+
seed_repo "$N"
|
|
330
|
+
git -C "$N" branch fixture-base HEAD
|
|
331
|
+
git -C "$N" switch -q -c case-ambiguous-undeclared
|
|
332
|
+
printf '| Note | Owner | Rationale | Status | Reference |\n| --- | --- | --- | --- | --- |\n| Fixture cross-owner bookkeeping note | `some-reviewer` | Recorded for traceability; this row makes no impact-chain claim | `routed` | compares how product-rd-workflow/SKILL.md and testing-strategy/SKILL.md phrase the same gate |\n' \
|
|
333
|
+
>> "$N/$LEDGER_REL"
|
|
334
|
+
git -C "$N" add -A
|
|
335
|
+
git -C "$N" commit -qm "round 1: an unrelated row naming two curated owners, declaring nothing"
|
|
336
|
+
# Guard: both owner keys must sit in the EVIDENCE cell, which is what ownership
|
|
337
|
+
# resolution reads. A fixture that put them in another column would resolve to
|
|
338
|
+
# nothing and pass against any gate.
|
|
339
|
+
git -C "$N" show "HEAD:$LEDGER_REL" | tail -1 | awk -F'|' '{print $6}' \
|
|
340
|
+
| grep -q 'product-rd-workflow/SKILL.md' \
|
|
341
|
+
|| fail "leg N fixture is a no-op: first owner key is not in the evidence cell"
|
|
342
|
+
git -C "$N" show "HEAD:$LEDGER_REL" | tail -1 | awk -F'|' '{print $6}' \
|
|
343
|
+
| grep -q 'testing-strategy/SKILL.md' \
|
|
344
|
+
|| fail "leg N fixture is a no-op: second owner key is not in the evidence cell"
|
|
345
|
+
run_gate "$N" fixture-base
|
|
346
|
+
report_leg "leg N (undeclared row naming two owners)" 0 "the blanket multi-owner block"
|
|
347
|
+
|
|
348
|
+
# ---------------------------------------------------------------------------
|
|
349
|
+
# Leg O — the same evasion as leg A, written with a path prefix an author uses
|
|
350
|
+
# without meaning anything unusual: `./skills/<owner>/...`. The locator's
|
|
351
|
+
# lookbehind refuses a match preceded by a path character, so before the prefix
|
|
352
|
+
# allowance this citation resolved to nothing and the row was silently skipped —
|
|
353
|
+
# putting a restored owner right back where leg A found it, one keystroke away.
|
|
354
|
+
# ---------------------------------------------------------------------------
|
|
355
|
+
O="$TMP/leg-o"
|
|
356
|
+
seed_repo "$O"
|
|
357
|
+
git -C "$O" branch fixture-base HEAD
|
|
358
|
+
git -C "$O" switch -q -c case-dotslash
|
|
359
|
+
mutate_owner_rule "$O" product-rd-workflow O
|
|
360
|
+
printf '| Fixture dot-slash row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | see ./skills/product-rd-workflow/references/design-note.md for the rationale |\n' \
|
|
361
|
+
"$(rule_anchor O)" >> "$O/$LEDGER_REL"
|
|
362
|
+
git -C "$O" add -A
|
|
363
|
+
git -C "$O" commit -qm "round 1: change the owner, cite it with a ./ prefixed path"
|
|
364
|
+
git -C "$O" checkout -q fixture-base -- skills/product-rd-workflow/SKILL.md
|
|
365
|
+
git -C "$O" commit -qm "owner restored to base bytes" -q
|
|
366
|
+
git -C "$O" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/' \
|
|
367
|
+
&& fail "leg O fixture is a no-op: the owner is still changed at HEAD"
|
|
368
|
+
run_gate "$O" fixture-base
|
|
369
|
+
report_leg "leg O (restored owner, ./ prefixed citation)" 1 "the path-prefix evasion" "impact_chain_row_vouches_for_unchanged_owner"
|
|
370
|
+
|
|
371
|
+
# Leg O2 — the rooted counterpart. The adversarial challenge found this one: the
|
|
372
|
+
# allowance covered `./skills/` but not `/skills/`, so a rooted citation resolved
|
|
373
|
+
# to nothing, and a row that resolves to nothing is skipped before any refusal
|
|
374
|
+
# can apply. One character of prefix was the whole evasion.
|
|
375
|
+
O2="$TMP/leg-o2"
|
|
376
|
+
seed_repo "$O2"
|
|
377
|
+
git -C "$O2" branch fixture-base HEAD
|
|
378
|
+
git -C "$O2" switch -q -c case-rooted
|
|
379
|
+
mutate_owner_rule "$O2" product-rd-workflow O2
|
|
380
|
+
printf '| Fixture rooted-path row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | see /skills/product-rd-workflow/references/design-note.md for the rationale |\n' \
|
|
381
|
+
"$(rule_anchor O2)" >> "$O2/$LEDGER_REL"
|
|
382
|
+
git -C "$O2" add -A
|
|
383
|
+
git -C "$O2" commit -qm "round 1: change the owner, cite it with a rooted path"
|
|
384
|
+
git -C "$O2" checkout -q fixture-base -- skills/product-rd-workflow/SKILL.md
|
|
385
|
+
git -C "$O2" commit -qm "owner restored to base bytes" -q
|
|
386
|
+
git -C "$O2" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/' \
|
|
387
|
+
&& fail "leg O2 fixture is a no-op: the owner is still changed at HEAD"
|
|
388
|
+
run_gate "$O2" fixture-base
|
|
389
|
+
report_leg "leg O2 (restored owner, rooted citation)" 1 "the rooted-path evasion" "impact_chain_row_vouches_for_unchanged_owner"
|
|
390
|
+
|
|
391
|
+
# Leg O3 — the remainder class. Enumerating the characters a filename may hold
|
|
392
|
+
# gets it wrong: a citation whose remainder starts `@`, or carries a non-ASCII
|
|
393
|
+
# character, failed to match, the optional `skills/` prefix backtracked onto the
|
|
394
|
+
# literal `skills`, and the row resolved to nothing — skipped before any refusal
|
|
395
|
+
# could apply. Both remainders are exercised in one row because a single
|
|
396
|
+
# unresolved citation is enough to lose the whole row.
|
|
397
|
+
O3="$TMP/leg-o3"
|
|
398
|
+
seed_repo "$O3"
|
|
399
|
+
git -C "$O3" branch fixture-base HEAD
|
|
400
|
+
git -C "$O3" switch -q -c case-remainder
|
|
401
|
+
mutate_owner_rule "$O3" product-rd-workflow O3
|
|
402
|
+
printf '| Fixture remainder row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | rationale in skills/product-rd-workflow/@design.md and skills/product-rd-workflow/设计说明.md |\n' \
|
|
403
|
+
"$(rule_anchor O3)" >> "$O3/$LEDGER_REL"
|
|
404
|
+
git -C "$O3" add -A
|
|
405
|
+
git -C "$O3" commit -qm "round 1: cite the owner with unusual but valid path remainders"
|
|
406
|
+
git -C "$O3" checkout -q fixture-base -- skills/product-rd-workflow/SKILL.md
|
|
407
|
+
git -C "$O3" commit -qm "owner restored to base bytes" -q
|
|
408
|
+
git -C "$O3" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/' \
|
|
409
|
+
&& fail "leg O3 fixture is a no-op: the owner is still changed at HEAD"
|
|
410
|
+
run_gate "$O3" fixture-base
|
|
411
|
+
report_leg "leg O3 (restored owner, unusual path remainder)" 1 "the remainder-class evasion" "impact_chain_row_vouches_for_unchanged_owner"
|
|
412
|
+
|
|
413
|
+
# Leg O4 — the Markdown-relative form, the fourth spelling a path parse missed
|
|
414
|
+
# and the one that ended the patching: an ordinary `[note](../../<owner>/…)` link
|
|
415
|
+
# from the ledger to a file inside the owner package. Legs O through O4 are kept
|
|
416
|
+
# together deliberately: each was a separate round of the same class, and the
|
|
417
|
+
# resolution is now a membership test over the owner vocabulary, which admits all
|
|
418
|
+
# four by construction rather than by four accepted spellings.
|
|
419
|
+
O4="$TMP/leg-o4"
|
|
420
|
+
seed_repo "$O4"
|
|
421
|
+
git -C "$O4" branch fixture-base HEAD
|
|
422
|
+
git -C "$O4" switch -q -c case-relative
|
|
423
|
+
mutate_owner_rule "$O4" product-rd-workflow O4
|
|
424
|
+
printf '| Fixture relative-link row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | rationale in [the design note](../../product-rd-workflow/references/design-note.md) |\n' \
|
|
425
|
+
"$(rule_anchor O4)" >> "$O4/$LEDGER_REL"
|
|
426
|
+
git -C "$O4" add -A
|
|
427
|
+
git -C "$O4" commit -qm "round 1: cite the owner through a Markdown-relative link"
|
|
428
|
+
git -C "$O4" checkout -q fixture-base -- skills/product-rd-workflow/SKILL.md
|
|
429
|
+
git -C "$O4" commit -qm "owner restored to base bytes" -q
|
|
430
|
+
git -C "$O4" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/' \
|
|
431
|
+
&& fail "leg O4 fixture is a no-op: the owner is still changed at HEAD"
|
|
432
|
+
run_gate "$O4" fixture-base
|
|
433
|
+
report_leg "leg O4 (restored owner, Markdown-relative link)" 1 "the relative-link evasion" "impact_chain_row_vouches_for_unchanged_owner"
|
|
434
|
+
|
|
435
|
+
# ---------------------------------------------------------------------------
|
|
436
|
+
# Leg P — the refusal an undeclared row still owes. It cites two curated owners
|
|
437
|
+
# but only one of them changed, so the OLD predicate filtered the citation down
|
|
438
|
+
# to that one owner, bound the row, and rejected it for its missing declaration.
|
|
439
|
+
# Sharing the new name-level count with undeclared rows turned that into a
|
|
440
|
+
# two-owner ambiguity that merely warns and drops — a refusal quietly lost while
|
|
441
|
+
# the change was billed as a tightening. A second, valid row declares the changed
|
|
442
|
+
# owner, so the demand is satisfied and this row's own rejection is the only
|
|
443
|
+
# thing the verdict can be measuring.
|
|
444
|
+
# ---------------------------------------------------------------------------
|
|
445
|
+
P1="$TMP/leg-p"
|
|
446
|
+
seed_repo "$P1"
|
|
447
|
+
git -C "$P1" branch fixture-base HEAD
|
|
448
|
+
git -C "$P1" switch -q -c case-undeclared-partial
|
|
449
|
+
mutate_owner_rule "$P1" product-rd-workflow P
|
|
450
|
+
append_valid_row "$P1" product-rd-workflow P "Fixture declaring row"
|
|
451
|
+
printf '| Fixture undeclared row | `downstream-executor` | no declaration here, only prose | `updated` | contrasts `product-rd-workflow/SKILL.md` with `testing-strategy/SKILL.md` |\n' \
|
|
452
|
+
>> "$P1/$LEDGER_REL"
|
|
453
|
+
git -C "$P1" add -A
|
|
454
|
+
git -C "$P1" commit -qm "round 1: a declaring row plus an undeclared row citing two owners"
|
|
455
|
+
git -C "$P1" diff --name-only fixture-base HEAD | grep -q '^skills/testing-strategy/' \
|
|
456
|
+
&& fail "leg P fixture is a no-op: the second cited owner must NOT be changed"
|
|
457
|
+
run_gate "$P1" fixture-base
|
|
458
|
+
report_leg "leg P (undeclared row, one cited owner changed)" 1 "the lost undeclared-row refusal" "impact_chain_behavior_evidence_missing"
|
|
459
|
+
|
|
460
|
+
# ---------------------------------------------------------------------------
|
|
461
|
+
# Leg S — the MALFORMED-ROW escape. One unescaped pipe puts a row outside the
|
|
462
|
+
# five-column parse, and a row outside the parse is invisible to every later
|
|
463
|
+
# check. That was survivable while it could only cost the row its own
|
|
464
|
+
# completeness; with a refusal now riding on surviving rows it becomes a way to
|
|
465
|
+
# buy silence: declare, name a byte-identical owner, add a stray pipe, and the
|
|
466
|
+
# range reports nothing at all. Blocking is scoped to that pair — declaration
|
|
467
|
+
# plus selected owner — so the register's other malformed prose keeps its
|
|
468
|
+
# advisory, which leg S2 pins.
|
|
469
|
+
# ---------------------------------------------------------------------------
|
|
470
|
+
S1="$TMP/leg-s"
|
|
471
|
+
seed_repo "$S1"
|
|
472
|
+
git -C "$S1" branch fixture-base HEAD
|
|
473
|
+
git -C "$S1" switch -q -c case-malformed
|
|
474
|
+
printf '| Fixture smuggled row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#nope | `updated` | rationale in skills/product-rd-workflow/references/note.md, see a|b for the table |\n' \
|
|
475
|
+
>> "$S1/$LEDGER_REL"
|
|
476
|
+
git -C "$S1" add -A
|
|
477
|
+
git -C "$S1" commit -qm "round 1: a declaring row for a selected owner with an unescaped pipe"
|
|
478
|
+
git -C "$S1" diff --name-only fixture-base HEAD | grep -q '^skills/product-rd-workflow/' \
|
|
479
|
+
&& fail "leg S fixture is a no-op: the owner must be byte-identical to base"
|
|
480
|
+
run_gate "$S1" fixture-base
|
|
481
|
+
report_leg "leg S (malformed row buys silence)" 1 "the malformed-row escape" "impact_chain_row_blocking_malformed"
|
|
482
|
+
|
|
483
|
+
# Leg S2 — the other side: a malformed row that makes no declaration and names no
|
|
484
|
+
# selected owner keeps its long-standing advisory. Without this the block is a
|
|
485
|
+
# blanket one and the register's other tables start failing merges on prose.
|
|
486
|
+
S2="$TMP/leg-s2"
|
|
487
|
+
seed_repo "$S2"
|
|
488
|
+
git -C "$S2" branch fixture-base HEAD
|
|
489
|
+
git -C "$S2" switch -q -c case-malformed-unrelated
|
|
490
|
+
printf '| Fixture unrelated malformed note | `some-reviewer` | recorded for traceability | `routed` | see the a|b column of the upstream table |\n' \
|
|
491
|
+
>> "$S2/$LEDGER_REL"
|
|
492
|
+
git -C "$S2" add -A
|
|
493
|
+
git -C "$S2" commit -qm "round 1: an unrelated malformed row"
|
|
494
|
+
run_gate "$S2" fixture-base
|
|
495
|
+
report_leg "leg S2 (unrelated malformed row stays advisory)" 0 "the blanket malformed block"
|
|
496
|
+
|
|
497
|
+
# ---------------------------------------------------------------------------
|
|
498
|
+
# Leg S3 — the same escape through a different structural rejection. A stray pipe
|
|
499
|
+
# is only one way out of the parse; an empty cell is another, and the row is just
|
|
500
|
+
# as invisible afterwards. Blocking the pipe alone would have moved the escape
|
|
501
|
+
# rather than closed it.
|
|
502
|
+
# ---------------------------------------------------------------------------
|
|
503
|
+
S3="$TMP/leg-s3"
|
|
504
|
+
seed_repo "$S3"
|
|
505
|
+
git -C "$S3" branch fixture-base HEAD
|
|
506
|
+
git -C "$S3" switch -q -c case-emptycell
|
|
507
|
+
printf '| Fixture empty-cell row | | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#nope | `updated` | rationale in skills/product-rd-workflow/references/note.md |\n' \
|
|
508
|
+
>> "$S3/$LEDGER_REL"
|
|
509
|
+
git -C "$S3" add -A
|
|
510
|
+
git -C "$S3" commit -qm "round 1: a declaring row for a selected owner with an empty cell"
|
|
511
|
+
run_gate "$S3" fixture-base
|
|
512
|
+
report_leg "leg S3 (empty cell buys the same silence)" 1 "the empty-cell escape" "impact_chain_row_blocking_malformed"
|
|
513
|
+
|
|
514
|
+
# ---------------------------------------------------------------------------
|
|
515
|
+
# Leg S4 — the repair must be accepted. A malformed declaring row corrected in a
|
|
516
|
+
# later round must stop blocking, or the gate refuses the very fix it demanded:
|
|
517
|
+
# the survival budget applies to malformed lines exactly as it does to parsed
|
|
518
|
+
# ones. Round 1 carries a sound row so its own demand is met; round 2 escapes the
|
|
519
|
+
# pipe AND lands the rule the corrected row anchors on, because a row is judged
|
|
520
|
+
# against the round it lands in — a correction that resolves only against an
|
|
521
|
+
# earlier round's diff is not yet a valid row, which is a different rule and not
|
|
522
|
+
# what this leg pins.
|
|
523
|
+
# ---------------------------------------------------------------------------
|
|
524
|
+
S4="$TMP/leg-s4"
|
|
525
|
+
seed_repo "$S4"
|
|
526
|
+
git -C "$S4" branch fixture-base HEAD
|
|
527
|
+
git -C "$S4" switch -q -c case-corrected
|
|
528
|
+
mutate_owner_rule "$S4" product-rd-workflow S4
|
|
529
|
+
append_valid_row "$S4" product-rd-workflow S4 "Fixture sound row"
|
|
530
|
+
printf '| Fixture to-be-corrected row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#%s | `updated` | rationale in skills/product-rd-workflow/references/note.md, see a|b |\n' \
|
|
531
|
+
"$(rule_anchor S4b)" >> "$S4/$LEDGER_REL"
|
|
532
|
+
git -C "$S4" add -A
|
|
533
|
+
git -C "$S4" commit -qm "round 1: a sound row plus a malformed declaring row"
|
|
534
|
+
perl -0pi -e 's/, see a\|b \|/, see a\\|b |/' "$S4/$LEDGER_REL"
|
|
535
|
+
grep -q 'see a\\|b' "$S4/$LEDGER_REL" || fail "leg S4 fixture is a no-op: the pipe was not escaped"
|
|
536
|
+
mutate_owner_rule "$S4" product-rd-workflow S4b
|
|
537
|
+
git -C "$S4" add -A
|
|
538
|
+
git -C "$S4" commit -qm "round 2: escape the pipe and land the rule the row anchors on"
|
|
539
|
+
run_gate "$S4" fixture-base
|
|
540
|
+
report_leg "leg S4 (a corrected malformed row stops blocking)" 0 "the un-repairable block"
|
|
541
|
+
# ---------------------------------------------------------------------------
|
|
542
|
+
# Leg S5 / S6 — the outer-pipe spellings. Markdown accepts a table row without a
|
|
543
|
+
# leading or trailing pipe, so dropping one is a fourth way out of the parse and
|
|
544
|
+
# was found separately from the stray pipe, the empty cell and the bad status
|
|
545
|
+
# word. The check is now defined by "this line did not become a row" rather than
|
|
546
|
+
# by which rejection turned it away, so these two close with the others rather
|
|
547
|
+
# than needing their own branch.
|
|
548
|
+
# ---------------------------------------------------------------------------
|
|
549
|
+
S5="$TMP/leg-s5"
|
|
550
|
+
seed_repo "$S5"
|
|
551
|
+
git -C "$S5" branch fixture-base HEAD
|
|
552
|
+
git -C "$S5" switch -q -c case-noleading
|
|
553
|
+
printf 'Fixture no-leading-pipe row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#nope | `updated` | rationale in skills/product-rd-workflow/references/note.md |\n' \
|
|
554
|
+
>> "$S5/$LEDGER_REL"
|
|
555
|
+
git -C "$S5" add -A
|
|
556
|
+
git -C "$S5" commit -qm "round 1: a declaring row without its leading pipe"
|
|
557
|
+
run_gate "$S5" fixture-base
|
|
558
|
+
report_leg "leg S5 (no leading pipe)" 1 "the missing-leading-pipe escape" "impact_chain_row_blocking_malformed"
|
|
559
|
+
|
|
560
|
+
S6="$TMP/leg-s6"
|
|
561
|
+
seed_repo "$S6"
|
|
562
|
+
git -C "$S6" branch fixture-base HEAD
|
|
563
|
+
git -C "$S6" switch -q -c case-notrailing
|
|
564
|
+
printf '| Fixture no-trailing-pipe row | `downstream-executor` | behavioral-evidence: RED-baseline; observed-failure: yes; firing-path: file:skills/product-rd-workflow/SKILL.md#nope | `updated` | rationale in skills/product-rd-workflow/references/note.md\n' \
|
|
565
|
+
>> "$S6/$LEDGER_REL"
|
|
566
|
+
git -C "$S6" add -A
|
|
567
|
+
git -C "$S6" commit -qm "round 1: a declaring row without its trailing pipe"
|
|
568
|
+
run_gate "$S6" fixture-base
|
|
569
|
+
report_leg "leg S6 (no trailing pipe)" 1 "the missing-trailing-pipe escape" "impact_chain_row_blocking_malformed"
|
|
570
|
+
|
|
571
|
+
echo
|
|
572
|
+
if [ "$legs_failed" -gt 0 ]; then
|
|
573
|
+
echo "test_impact_chain_round_attribution: $legs_failed/18 legs RED (forms confirmed reproducing)"
|
|
574
|
+
exit 1
|
|
575
|
+
fi
|
|
576
|
+
echo "test_impact_chain_round_attribution: ok (all forms closed)"
|