@windyroad/itil 0.61.1 → 0.61.2
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/.claude-plugin/plugin.json +1 -1
- package/package.json +7 -2
- package/agents/test/fixtures/proceed-new-genuinely-new.md +0 -43
- package/agents/test/fixtures/proceed-new-subtle-sibling.md +0 -47
- package/agents/test/fixtures/regression-p347-vs-p346.md +0 -54
- package/agents/test/hang-off-check.bats +0 -225
- package/hooks/test/block-list.bats +0 -153
- package/hooks/test/command-detect.bats +0 -181
- package/hooks/test/itil-assistant-output-gate.bats +0 -114
- package/hooks/test/itil-assistant-output-review.bats +0 -224
- package/hooks/test/itil-bash-polling-antipattern-detect.bats +0 -154
- package/hooks/test/itil-changeset-discipline.bats +0 -603
- package/hooks/test/itil-claude-space-protection.bats +0 -294
- package/hooks/test/itil-commit-trailer-transition-advisory.bats +0 -80
- package/hooks/test/itil-correction-detect.bats +0 -189
- package/hooks/test/itil-deferral-cadence-gate.bats +0 -187
- package/hooks/test/itil-fictional-defer-detect.bats +0 -292
- package/hooks/test/itil-fix-title-lifecycle-advisory.bats +0 -129
- package/hooks/test/itil-mid-loop-ask-detect.bats +0 -220
- package/hooks/test/itil-no-implement-draft-gate.bats +0 -210
- package/hooks/test/itil-pending-questions-surface.bats +0 -307
- package/hooks/test/itil-readme-refresh-discipline.bats +0 -642
- package/hooks/test/itil-rfc-oversight-nudge.bats +0 -83
- package/hooks/test/itil-rfc-trailer-advisory.bats +0 -375
- package/hooks/test/itil-story-mirror-migration-nudge.bats +0 -122
- package/hooks/test/manage-problem-enforce-create.bats +0 -424
- package/hooks/test/p057-staging-trap-detect.bats +0 -231
- package/hooks/test/pre-publish-intake-gate.bats +0 -144
- package/hooks/test/runtime-sid-marker.bats +0 -90
- package/hooks/test/session-id.bats +0 -370
- package/scripts/migrate-problems-add-type.sh +0 -116
- package/scripts/test/catchup-scan.bats +0 -274
- package/scripts/test/check-afk-accept-eligible.bats +0 -310
- package/scripts/test/check-fail-soft-skip-discipline.bats +0 -172
- package/scripts/test/check-fix-rfc-trace.bats +0 -164
- package/scripts/test/check-locale-discipline.bats +0 -291
- package/scripts/test/check-problems-readme-budget.bats +0 -192
- package/scripts/test/check-rfc-has-stories.bats +0 -69
- package/scripts/test/check-rfc-rejected-alternatives.bats +0 -108
- package/scripts/test/check-rfc-stories-ratified.bats +0 -82
- package/scripts/test/check-upstream-responses.bats +0 -503
- package/scripts/test/classify-readme-drift.bats +0 -392
- package/scripts/test/derive-first-dispatch.bats +0 -274
- package/scripts/test/derive-release-vehicle.bats +0 -454
- package/scripts/test/detect-unratified-stories-maps.bats +0 -60
- package/scripts/test/dual-tolerant-glob-rfc-002-t2.bats +0 -309
- package/scripts/test/effort-tally.bats +0 -170
- package/scripts/test/evaluate-relevance.bats +0 -773
- package/scripts/test/kind-a-commands.bats +0 -46
- package/scripts/test/mark-create-gate.bats +0 -59
- package/scripts/test/mark-story-oversight-confirmed.bats +0 -53
- package/scripts/test/migrate-problems-add-type.bats +0 -280
- package/scripts/test/migrate-story-status-mirror.bats +0 -167
- package/scripts/test/no-type-regression-guard.bats +0 -74
- package/scripts/test/oversight-mirror-corpus-lint.bats +0 -150
- package/scripts/test/plugin-exercise-index.bats +0 -386
- package/scripts/test/plugin-maturity-doc-lint.bats +0 -470
- package/scripts/test/plugin-maturity-populate.bats +0 -631
- package/scripts/test/plugin-maturity-render.bats +0 -469
- package/scripts/test/plugin-validate-ci-gate.bats +0 -208
- package/scripts/test/reconcile-readme.bats +0 -1007
- package/scripts/test/reconcile-rfcs.bats +0 -496
- package/scripts/test/reconcile-stories.bats +0 -173
- package/scripts/test/reconcile-story-maps.bats +0 -74
- package/scripts/test/release-watch-poll-loop.bats +0 -180
- package/scripts/test/resolve-governance-plugin-dirs.bats +0 -78
- package/scripts/test/rfc-stories-extension.bats +0 -175
- package/scripts/test/skill-invocations.bats +0 -535
- package/scripts/test/skill-md-dual-tolerant-coverage-rfc-002-t3.bats +0 -374
- package/scripts/test/story-oversight-lib.bats +0 -190
- package/scripts/test/update-jtbd-references-related-problems.bats +0 -178
- package/scripts/test/update-problem-references-section.bats +0 -242
- package/scripts/test/update-problem-rfcs-section.bats +0 -242
- package/scripts/test/update-references-section-sibling-helpers.bats +0 -80
- package/scripts/test/update-rfc-commits-section.bats +0 -77
- package/scripts/test/verify-iter-summary.bats +0 -196
- package/scripts/test/working-the-problem-traversal.bats +0 -116
- package/skills/capture-problem/test/capture-problem-step-1-5b-jtbd-trace.bats +0 -398
- package/skills/capture-problem/test/capture-problem.bats +0 -389
- package/skills/capture-story/test/capture-story-behavioural.bats +0 -317
- package/skills/capture-story-map/test/capture-story-map-behavioural.bats +0 -98
- package/skills/close-incident/test/close-incident-contract.bats +0 -146
- package/skills/link-incident/test/link-incident-contract.bats +0 -125
- package/skills/list-incidents/test/list-incidents-contract.bats +0 -115
- package/skills/list-problems/test/list-problems-contract.bats +0 -100
- package/skills/list-stories/test/list-stories-contract.bats +0 -127
- package/skills/list-story-maps/test/list-story-maps-contract.bats +0 -46
- package/skills/manage-incident/test/manage-incident-adr-044-contract.bats +0 -206
- package/skills/manage-incident/test/manage-incident-close-forwarder.bats +0 -67
- package/skills/manage-incident/test/manage-incident-link-forwarder.bats +0 -67
- package/skills/manage-incident/test/manage-incident-list-forwarder.bats +0 -68
- package/skills/manage-incident/test/manage-incident-mitigate-forwarder.bats +0 -66
- package/skills/manage-incident/test/manage-incident-restore-forwarder.bats +0 -66
- package/skills/manage-incident/test/manage-incident.bats +0 -171
- package/skills/manage-problem/test/manage-problem-adr-044-step4-derive-first.bats +0 -151
- package/skills/manage-problem/test/manage-problem-auto-migrate-step.bats +0 -53
- package/skills/manage-problem/test/manage-problem-concern-boundary.bats +0 -64
- package/skills/manage-problem/test/manage-problem-effort-buckets.bats +0 -56
- package/skills/manage-problem/test/manage-problem-external-root-cause-detection.bats +0 -119
- package/skills/manage-problem/test/manage-problem-first-run-intake-prompt.bats +0 -43
- package/skills/manage-problem/test/manage-problem-git-mv-restage-reminder.bats +0 -48
- package/skills/manage-problem/test/manage-problem-id-collision-guard.bats +0 -39
- package/skills/manage-problem/test/manage-problem-list-forwarder.bats +0 -66
- package/skills/manage-problem/test/manage-problem-next-id-origin-lookup.bats +0 -50
- package/skills/manage-problem/test/manage-problem-no-prose-options.bats +0 -74
- package/skills/manage-problem/test/manage-problem-output-formatting.bats +0 -30
- package/skills/manage-problem/test/manage-problem-parked-and-cache.bats +0 -73
- package/skills/manage-problem/test/manage-problem-readme-refresh-on-transition.bats +0 -62
- package/skills/manage-problem/test/manage-problem-readme-tie-break-order.bats +0 -318
- package/skills/manage-problem/test/manage-problem-readme-vq-sort-order.bats +0 -206
- package/skills/manage-problem/test/manage-problem-release-vehicle-seed.bats +0 -83
- package/skills/manage-problem/test/manage-problem-review-forwarder.bats +0 -71
- package/skills/manage-problem/test/manage-problem-step-9d-recovery-path.bats +0 -97
- package/skills/manage-problem/test/manage-problem-transition-forwarder.bats +0 -96
- package/skills/manage-problem/test/manage-problem-transitive-dependencies.bats +0 -365
- package/skills/manage-problem/test/manage-problem-verification-detection.bats +0 -64
- package/skills/manage-problem/test/manage-problem-verification-pending.bats +0 -114
- package/skills/manage-problem/test/manage-problem-work-forwarder.bats +0 -88
- package/skills/manage-story/test/manage-story-contract.bats +0 -174
- package/skills/manage-story-map/test/manage-story-map-contract.bats +0 -63
- package/skills/mitigate-incident/test/mitigate-incident-contract.bats +0 -258
- package/skills/reconcile-readme/test/reconcile-readme-contract.bats +0 -201
- package/skills/report-upstream/test/report-upstream-contract.bats +0 -394
- package/skills/restore-incident/test/restore-incident-contract.bats +0 -170
- package/skills/review-problems/test/inbound-channels-cache-shape.bats +0 -127
- package/skills/review-problems/test/inbound-discovery-contract.bats +0 -383
- package/skills/review-problems/test/jtbd-301-verdict-shape-contract.bats +0 -225
- package/skills/review-problems/test/review-problems-contract.bats +0 -235
- package/skills/review-problems/test/review-problems-likely-verified-cell-shape.bats +0 -229
- package/skills/scaffold-intake/test/scaffold-intake-contract.bats +0 -126
- package/skills/scaffold-intake/test/scaffold-intake-fixture.bats +0 -164
- package/skills/scaffold-intake/test/scaffold-intake-secrets-absent.bats +0 -87
- package/skills/transition-problem/test/transition-problem-contract.bats +0 -285
- package/skills/transition-problems/test/transition-problems-contract.bats +0 -331
- package/skills/update-upstream/test/update-upstream-contract.bats +0 -375
- package/skills/work-problem/test/work-problem-contract.bats +0 -294
- package/skills/work-problems/test/work-problems-above-appetite-remediation.bats +0 -139
- package/skills/work-problems/test/work-problems-adr-013-rule-6-p352-amendment.bats +0 -166
- package/skills/work-problems/test/work-problems-auto-migrate-step.bats +0 -57
- package/skills/work-problems/test/work-problems-cost-logging.bats +0 -109
- package/skills/work-problems/test/work-problems-deviation-candidate-shape.bats +0 -121
- package/skills/work-problems/test/work-problems-first-run-intake-prompt.bats +0 -36
- package/skills/work-problems/test/work-problems-inter-iteration-verify.bats +0 -59
- package/skills/work-problems/test/work-problems-mid-loop-userpromptsubmit-handler.bats +0 -69
- package/skills/work-problems/test/work-problems-no-mid-loop-asking.bats +0 -192
- package/skills/work-problems/test/work-problems-p341-pre-all-done-gate.bats +0 -122
- package/skills/work-problems/test/work-problems-p342-r007-derive-then-pass-flags.bats +0 -170
- package/skills/work-problems/test/work-problems-p342-retro-auto-ticket-carveout.bats +0 -120
- package/skills/work-problems/test/work-problems-preflight-failure-handling.bats +0 -248
- package/skills/work-problems/test/work-problems-preflight-session-continuity.bats +0 -139
- package/skills/work-problems/test/work-problems-preflight.bats +0 -69
- package/skills/work-problems/test/work-problems-release-cadence.bats +0 -63
- package/skills/work-problems/test/work-problems-step-0-iter-error-staleness.bats +0 -93
- package/skills/work-problems/test/work-problems-step-0b-cache-staleness-behavioural.bats +0 -138
- package/skills/work-problems/test/work-problems-step-0c-deferred-placeholder-staleness-behavioural.bats +0 -238
- package/skills/work-problems/test/work-problems-step-0d-outbound-responses-staleness-behavioural.bats +0 -174
- package/skills/work-problems/test/work-problems-step-2-5-routing.bats +0 -80
- package/skills/work-problems/test/work-problems-step-2-5b-cross-halt-routing.bats +0 -149
- package/skills/work-problems/test/work-problems-step-3-5-jtbd-ratification-predicate.bats +0 -191
- package/skills/work-problems/test/work-problems-step-5-bats-polling-discipline.bats +0 -91
- package/skills/work-problems/test/work-problems-step-5-delegation.bats +0 -333
- package/skills/work-problems/test/work-problems-step-5-idle-timeout-sigterm.bats +0 -421
- package/skills/work-problems/test/work-problems-step-5-is-error-transient-halt.bats +0 -278
- package/skills/work-problems/test/work-problems-step-5-iter-changeset-required.bats +0 -95
- package/skills/work-problems/test/work-problems-step-5-prompt-body-re-grounding.bats +0 -128
- package/skills/work-problems/test/work-problems-step-5-stream-timeout-salvage.bats +0 -251
- package/skills/work-problems/test/work-problems-step-6-5-always-drain.bats +0 -203
- package/skills/work-problems/test/work-problems-step-6-5-cache-refresh-chain.bats +0 -174
- package/skills/work-problems/test/work-problems-step-6-5-fix-and-continue.bats +0 -254
- package/skills/work-problems/test/work-problems-step-6-5-postrelease-kv-callback.bats +0 -209
- package/skills/work-problems/test/work-problems-stop-condition-questions.bats +0 -85
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bats
|
|
2
|
-
|
|
3
|
-
# tdd-review: structural-permitted (justification: P012 skill testing
|
|
4
|
-
# harness scope is open; no behavioural alternative for SKILL.md prose-
|
|
5
|
-
# template structural assertions today. ADR-052 Migration clause permits
|
|
6
|
-
# structural retrofit-via-justification when the linked harness-gap ticket
|
|
7
|
-
# has not yet shipped the primitives. The paired promptfoo eval at
|
|
8
|
-
# packages/itil/skills/update-upstream/eval/promptfooconfig.yaml carries
|
|
9
|
-
# the behavioural Tier-A/B coverage per ADR-075 Amendment 2026-06-02.
|
|
10
|
-
# Provenance: P080 (original bidirectional contract) + P363 / ADR-024
|
|
11
|
-
# amendment 2026-06-22 (inbound-origin verdict dispatch leg) + P363 rework
|
|
12
|
-
# 2026-06-23 (four user directives — LLM-generated verdict, workaround
|
|
13
|
-
# provenance-credit, visibility-gated anti-leakage, cog-a11y gate),
|
|
14
|
-
# behaviourally paired by the inbound eval cases in promptfooconfig.yaml.
|
|
15
|
-
# The lockstep transition-problem/manage-problem grep check is an inherent
|
|
16
|
-
# copy-not-move drift detector (ADR-010/P362) with no behavioural form.)
|
|
17
|
-
#
|
|
18
|
-
# Doc-lint structural test (Permitted Exception per ADR-005 — structural
|
|
19
|
-
# SKILL.md content checks, not behavioural). Mirrors the doc-lint pattern
|
|
20
|
-
# established in ADR-011 and ADR-027 Confirmation tests and used by the
|
|
21
|
-
# sibling report-upstream contract test.
|
|
22
|
-
#
|
|
23
|
-
# Asserts the update-upstream skill's SKILL.md encodes the contract
|
|
24
|
-
# documented in ADR-024 amendment (P080):
|
|
25
|
-
# - sibling-skill split per ADR-010 amended
|
|
26
|
-
# - reads ## Reported Upstream from the local ticket
|
|
27
|
-
# - three transition templates (Open→KE, KE→Verifying, Verifying→Closed)
|
|
28
|
-
# - composes through external-comms + voice-tone gates (AND, not OR)
|
|
29
|
-
# - within appetite → gh issue comment; on Verifying→Closed also gh issue close
|
|
30
|
-
# - above appetite → silent risk-reduce + re-score; if still above, queue
|
|
31
|
-
# to ## Queued Upstream Update + outstanding_questions (NOT halt the loop)
|
|
32
|
-
# - back-writes to ## Upstream Lifecycle Updates (append-only log)
|
|
33
|
-
# - ADR-014 single-commit grain when fired from transition-problem Step 7
|
|
34
|
-
|
|
35
|
-
setup() {
|
|
36
|
-
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
|
|
37
|
-
SKILL_MD="$REPO_ROOT/packages/itil/skills/update-upstream/SKILL.md"
|
|
38
|
-
EVAL_CONFIG="$REPO_ROOT/packages/itil/skills/update-upstream/eval/promptfooconfig.yaml"
|
|
39
|
-
TRANSITION_MD="$REPO_ROOT/packages/itil/skills/transition-problem/SKILL.md"
|
|
40
|
-
MANAGE_MD="$REPO_ROOT/packages/itil/skills/manage-problem/SKILL.md"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@test "update-upstream: SKILL.md exists" {
|
|
44
|
-
[ -f "$SKILL_MD" ]
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
@test "update-upstream: SKILL.md declares sibling-skill split per ADR-010 amended (P080 user direction (a))" {
|
|
48
|
-
# User direction (a) — new sibling skill, not a mode flag on report-upstream.
|
|
49
|
-
run grep -F 'sibling' "$SKILL_MD"
|
|
50
|
-
[ "$status" -eq 0 ]
|
|
51
|
-
run grep -F 'ADR-010' "$SKILL_MD"
|
|
52
|
-
[ "$status" -eq 0 ]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
@test "update-upstream: SKILL.md cross-references ADR-024 amendment (P080)" {
|
|
56
|
-
run grep -F 'ADR-024' "$SKILL_MD"
|
|
57
|
-
[ "$status" -eq 0 ]
|
|
58
|
-
run grep -iE 'P080' "$SKILL_MD"
|
|
59
|
-
[ "$status" -eq 0 ]
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
@test "update-upstream: SKILL.md reads ## Reported Upstream from the local ticket (P080 contract)" {
|
|
63
|
-
# The skill reads the section that /wr-itil:report-upstream Step 7
|
|
64
|
-
# writes (per ADR-024 Confirmation criterion 3a). Without this read, the
|
|
65
|
-
# skill has no upstream URL to comment on.
|
|
66
|
-
run grep -F '## Reported Upstream' "$SKILL_MD"
|
|
67
|
-
[ "$status" -eq 0 ]
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
@test "update-upstream: SKILL.md documents three transition templates (Open→KE, KE→Verifying, Verifying→Closed)" {
|
|
71
|
-
# Each transition has its own template — investigation findings vs release
|
|
72
|
-
# info vs closure thanks. ADR-024 amendment authority pins all three.
|
|
73
|
-
run grep -iE 'Open[[:space:]]*[—\-][[:space:]]*[>›]?[[:space:]]*Known Error|Open[[:space:]]*→[[:space:]]*Known Error' "$SKILL_MD"
|
|
74
|
-
[ "$status" -eq 0 ]
|
|
75
|
-
run grep -iE 'Known Error[[:space:]]*[—\-][[:space:]]*[>›]?[[:space:]]*Verification Pending|Known Error[[:space:]]*→[[:space:]]*Verification Pending' "$SKILL_MD"
|
|
76
|
-
[ "$status" -eq 0 ]
|
|
77
|
-
run grep -iE 'Verification Pending[[:space:]]*[—\-][[:space:]]*[>›]?[[:space:]]*Closed|Verification Pending[[:space:]]*→[[:space:]]*Closed' "$SKILL_MD"
|
|
78
|
-
[ "$status" -eq 0 ]
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
@test "update-upstream: SKILL.md composes through external-comms gate (P080 user direction (b) + ADR-028)" {
|
|
82
|
-
# User direction (b) — risk-gated. The gate is wr-risk-scorer:external-comms
|
|
83
|
-
# per ADR-028's third-evaluator extension point (the same gate the post-
|
|
84
|
-
# P270 amendment uses for the initial-filing path).
|
|
85
|
-
run grep -F 'wr-risk-scorer:external-comms' "$SKILL_MD"
|
|
86
|
-
[ "$status" -eq 0 ]
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@test "update-upstream: SKILL.md composes through voice-tone gate (P080 user direction (b) + ADR-028)" {
|
|
90
|
-
# User direction (b) — voice-tone gated. The gate is wr-voice-tone:agent
|
|
91
|
-
# firing on gh issue comment / gh issue close per ADR-028.
|
|
92
|
-
run grep -F 'ADR-028' "$SKILL_MD"
|
|
93
|
-
[ "$status" -eq 0 ]
|
|
94
|
-
run grep -iE 'voice-tone gate' "$SKILL_MD"
|
|
95
|
-
[ "$status" -eq 0 ]
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
@test "update-upstream: SKILL.md gates compose AND (both must pass) not OR (P080 user direction (c))" {
|
|
99
|
-
# User direction (c) — same external-comms gate composition pattern as
|
|
100
|
-
# inbound (P079). That pattern is AND, not OR — one fail blocks the post.
|
|
101
|
-
# The SKILL.md must frame composition explicitly so adopters do not read
|
|
102
|
-
# it as independent gates.
|
|
103
|
-
run grep -iE 'voice-tone fail.*queue|voice-tone.*FAIL.*queue|FAIL.*identically' "$SKILL_MD"
|
|
104
|
-
[ "$status" -eq 0 ]
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
@test "update-upstream: SKILL.md within-appetite posts via gh issue comment" {
|
|
108
|
-
# Within-appetite path posts via gh issue comment with the matched URL's
|
|
109
|
-
# issue number — same gh CLI surface as report-upstream Step 5c.
|
|
110
|
-
run grep -F 'gh issue comment' "$SKILL_MD"
|
|
111
|
-
[ "$status" -eq 0 ]
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
@test "update-upstream: SKILL.md Verifying→Closed also runs gh issue close (symmetric audit trail)" {
|
|
115
|
-
# JTBD-201 symmetric audit trail outcome — when the local ticket goes
|
|
116
|
-
# .closed.md the upstream issue must also close. Without gh issue close
|
|
117
|
-
# the upstream tracker accumulates stale-looking open issues.
|
|
118
|
-
run grep -F 'gh issue close' "$SKILL_MD"
|
|
119
|
-
[ "$status" -eq 0 ]
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
@test "update-upstream: SKILL.md above-appetite saves to ## Queued Upstream Update (not the report rename)" {
|
|
123
|
-
# ADR-024 amendment (P080) — the lifecycle-update queue section is named
|
|
124
|
-
# ## Queued Upstream Update, distinct from the initial-filing ## Queued
|
|
125
|
-
# Upstream Report (renamed per the 2026-06-04 second-amendment leaf (c)).
|
|
126
|
-
# Distinct sections so a single local ticket can carry both without collision.
|
|
127
|
-
run grep -F '## Queued Upstream Update' "$SKILL_MD"
|
|
128
|
-
[ "$status" -eq 0 ]
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@test "update-upstream: SKILL.md above-appetite queues outstanding_questions (does NOT halt the orchestrator per P352)" {
|
|
132
|
-
# P352 queue-and-continue — same shape as the post-P270 initial-filing
|
|
133
|
-
# path. The above-appetite branch must NOT halt the loop; the queued
|
|
134
|
-
# entry surfaces at the existing batched-AskUserQuestion end-of-loop gate.
|
|
135
|
-
run grep -iE 'outstanding_questions|queue-and-continue|P352' "$SKILL_MD"
|
|
136
|
-
[ "$status" -eq 0 ]
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@test "update-upstream: SKILL.md silent risk-reduce + re-score is mechanical per ADR-044 (no per-iter AskUserQuestion)" {
|
|
140
|
-
# ADR-044 framework-resolution boundary — the risk-reduce + re-score is
|
|
141
|
-
# silent (mechanical); per-iter AskUserQuestion for risk-reduce vocabulary
|
|
142
|
-
# is the lazy-deferral anti-pattern P132 closes.
|
|
143
|
-
run grep -iE 'silent risk-reduce|mechanical.*ADR-044|ADR-044.*mechanical' "$SKILL_MD"
|
|
144
|
-
[ "$status" -eq 0 ]
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
@test "update-upstream: SKILL.md back-writes to ## Upstream Lifecycle Updates (append-only log)" {
|
|
148
|
-
# The audit-trail back-write mirrors the ## Reported Upstream back-write
|
|
149
|
-
# in report-upstream Step 7 (per ADR-024 Confirmation criterion 3a),
|
|
150
|
-
# extended to log every transition.
|
|
151
|
-
run grep -F '## Upstream Lifecycle Updates' "$SKILL_MD"
|
|
152
|
-
[ "$status" -eq 0 ]
|
|
153
|
-
run grep -iE 'append-only|never overwritten|append.*entry' "$SKILL_MD"
|
|
154
|
-
[ "$status" -eq 0 ]
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
@test "update-upstream: SKILL.md AFK behaviour summary table exists (architect review)" {
|
|
158
|
-
# Mirrors report-upstream's AFK behaviour summary table — the canonical
|
|
159
|
-
# place where adopters look up the AFK routing for each branch.
|
|
160
|
-
run grep -F 'AFK behaviour summary' "$SKILL_MD"
|
|
161
|
-
[ "$status" -eq 0 ]
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
@test "update-upstream: SKILL.md cites ADR-014 single-commit grain (transition + back-write + upstream post)" {
|
|
165
|
-
# When fired from transition-problem Step 7, the upstream comment +
|
|
166
|
-
# back-write + ticket rename + README refresh ride the SAME commit per
|
|
167
|
-
# ADR-014 single-commit grain.
|
|
168
|
-
run grep -F 'ADR-014' "$SKILL_MD"
|
|
169
|
-
[ "$status" -eq 0 ]
|
|
170
|
-
run grep -iE 'single-commit|same single commit|same commit' "$SKILL_MD"
|
|
171
|
-
[ "$status" -eq 0 ]
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@test "update-upstream: SKILL.md no-op exit on missing ## Reported Upstream (cheap unconditional firing)" {
|
|
175
|
-
# The trigger fires on every transition unconditionally; the no-op exit
|
|
176
|
-
# absorbs the misses (most tickets have no ## Reported Upstream). Without
|
|
177
|
-
# the no-op exit, every transition pays a decision cost.
|
|
178
|
-
run grep -iE 'no-op exit|nothing to update|exit cleanly' "$SKILL_MD"
|
|
179
|
-
[ "$status" -eq 0 ]
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
@test "update-upstream: SKILL.md no-invention rule on template-filling (reporter-trust guard)" {
|
|
183
|
-
# If a cited local-ticket section is absent, write the explicit "absent"
|
|
184
|
-
# phrasing rather than invent content. The risk + voice-tone gates cannot
|
|
185
|
-
# guard against invented technical claims; the no-invention rule does.
|
|
186
|
-
run grep -iE 'no.invention|do not invent|never invent|rather than invent|absent.*phrasing|"absent"' "$SKILL_MD"
|
|
187
|
-
[ "$status" -eq 0 ]
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
@test "update-upstream: SKILL.md annotates JTBD-301 + JTBD-001 (jtbd-lead review)" {
|
|
191
|
-
# JTBD-301 plugin-user reporter feedback loop AND JTBD-001 solo-developer
|
|
192
|
-
# without-slowing-down are the load-bearing JTBDs. The jtbd-lead review
|
|
193
|
-
# required both annotations.
|
|
194
|
-
run grep -F 'JTBD-301' "$SKILL_MD"
|
|
195
|
-
[ "$status" -eq 0 ]
|
|
196
|
-
run grep -F 'JTBD-001' "$SKILL_MD"
|
|
197
|
-
[ "$status" -eq 0 ]
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@test "update-upstream: SKILL.md documents transition-problem Step 7 trigger wire-in (P080 invocation contract)" {
|
|
201
|
-
# The advisory subsection in transition-problem Step 7 fires this skill
|
|
202
|
-
# when ## Reported Upstream is present. The SKILL.md must reference the
|
|
203
|
-
# trigger surface so adopters understand the invocation contract.
|
|
204
|
-
run grep -iE 'transition-problem.*Step 7|Step 7.*transition-problem|fired from.*transition' "$SKILL_MD"
|
|
205
|
-
[ "$status" -eq 0 ]
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
# ─── Inbound-origin verdict dispatch leg (P363 / ADR-024 amendment 2026-06-22) ─
|
|
209
|
-
|
|
210
|
-
@test "update-upstream: SKILL.md documents the inbound-origin verdict dispatch leg (P363)" {
|
|
211
|
-
# The skill reads the **Origin**: inbound-reported (#NN) field (ADR-076)
|
|
212
|
-
# in addition to ## Reported Upstream, so inbound reporters get a verdict.
|
|
213
|
-
run grep -iE 'Inbound-origin verdict dispatch' "$SKILL_MD"
|
|
214
|
-
[ "$status" -eq 0 ]
|
|
215
|
-
run grep -F 'inbound-reported (#NN)' "$SKILL_MD"
|
|
216
|
-
[ "$status" -eq 0 ]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
@test "update-upstream: SKILL.md no-op exit requires BOTH surfaces absent (section AND inbound Origin)" {
|
|
220
|
-
# The dual-direction no-op exit fires only when NEITHER the outbound
|
|
221
|
-
# ## Reported Upstream section NOR the inbound **Origin** field is present.
|
|
222
|
-
run grep -iE 'no inbound Origin|NEITHER .*Reported Upstream.*Origin|both are absent' "$SKILL_MD"
|
|
223
|
-
[ "$status" -eq 0 ]
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
@test "update-upstream: SKILL.md inbound leg resolves the originating issue on OUR OWN repo (not external upstream)" {
|
|
227
|
-
# Inbound issues are filed AGAINST us — the comment posts on our own repo,
|
|
228
|
-
# resolved via gh default / gh repo view, NOT an external upstream owner/repo.
|
|
229
|
-
run grep -iE 'gh repo view|our own repo|own repo' "$SKILL_MD"
|
|
230
|
-
[ "$status" -eq 0 ]
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
@test "update-upstream: SKILL.md inbound leg has an idempotency guard (gh issue view --json comments)" {
|
|
234
|
-
# Before posting, scan existing comments for the verdict marker
|
|
235
|
-
# (package@version + commit SHA) and skip if already posted.
|
|
236
|
-
run grep -F 'gh issue view' "$SKILL_MD"
|
|
237
|
-
[ "$status" -eq 0 ]
|
|
238
|
-
run grep -iE 'idempoten' "$SKILL_MD"
|
|
239
|
-
[ "$status" -eq 0 ]
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
@test "update-upstream: SKILL.md inbound templates carry the P229 anti-leakage rule (reporter-facing, no internal vocab)" {
|
|
243
|
-
# Reporter-facing comment bodies on our own repo MUST NOT leak Step IDs,
|
|
244
|
-
# branch names, classification tokens, or P/ADR/JTBD IDs as carriers of
|
|
245
|
-
# meaning. The released @windyroad/<pkg>@<version> is the only permitted
|
|
246
|
-
# structured token. Mirrors ADR-062 safe-and-valid acknowledgement shape.
|
|
247
|
-
run grep -iE 'anti-leakage|reporter-surface prose|reporter-facing' "$SKILL_MD"
|
|
248
|
-
[ "$status" -eq 0 ]
|
|
249
|
-
run grep -F 'P229' "$SKILL_MD"
|
|
250
|
-
[ "$status" -eq 0 ]
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
@test "update-upstream: SKILL.md inbound leg keeps the SAME dual gate composition (no weaker path)" {
|
|
254
|
-
# The inbound comment routes through the SAME external-comms + voice-tone
|
|
255
|
-
# dual gate as the outbound path — no weaker path for inbound.
|
|
256
|
-
run grep -iE 'SAME .*external-comms .*voice-tone|same.*dual gate' "$SKILL_MD"
|
|
257
|
-
[ "$status" -eq 0 ]
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
@test "update-upstream: SKILL.md inbound Verifying→Closed also closes the own-repo issue (addresses #97-unclosed witness)" {
|
|
261
|
-
# P211 #97 was silent AND unclosed. The inbound leg runs gh issue close
|
|
262
|
-
# on the own repo on the Verifying→Closed transition.
|
|
263
|
-
run grep -iE 'posted-inbound-comment-and-closed|gh issue close .*OWN' "$SKILL_MD"
|
|
264
|
-
[ "$status" -eq 0 ]
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
@test "update-upstream: SKILL.md both-direction tickets fire both legs independently" {
|
|
268
|
-
# A ticket reported upstream AND reported against us inbound fires both
|
|
269
|
-
# dispatches independently — one above-appetite leg queues only itself.
|
|
270
|
-
run grep -iE 'Both-direction|both.*legs.*independent|fire .*independently' "$SKILL_MD"
|
|
271
|
-
[ "$status" -eq 0 ]
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
@test "update-upstream: SKILL.md back-writes inbound entries direction-tagged so P249 poller is uncontaminated" {
|
|
275
|
-
# Inbound entries log to ## Upstream Lifecycle Updates (NOT ## Reported
|
|
276
|
-
# Upstream) so /wr-itil:check-upstream-responses (P249) is not contaminated.
|
|
277
|
-
run grep -F 'P249' "$SKILL_MD"
|
|
278
|
-
[ "$status" -eq 0 ]
|
|
279
|
-
run grep -iE 'inbound.*disclosure path|posted-inbound-comment' "$SKILL_MD"
|
|
280
|
-
[ "$status" -eq 0 ]
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
# ─── P363 rework 2026-06-23 — four user directives ────────────────────────────
|
|
284
|
-
|
|
285
|
-
@test "update-upstream: SKILL.md inbound verdict is LLM-generated per-context, not templated (Directive 1)" {
|
|
286
|
-
# Directive 1 — templates produce cold, patterned prose; the inbound verdict
|
|
287
|
-
# is GENERATED from ticket context via per-transition generation prompts the
|
|
288
|
-
# agent reads at runtime, NOT filled from canned template bodies.
|
|
289
|
-
run grep -iE 'LLM-generated|generated from the local ticket|generation prompt' "$SKILL_MD"
|
|
290
|
-
[ "$status" -eq 0 ]
|
|
291
|
-
run grep -F 'no templates' "$SKILL_MD"
|
|
292
|
-
[ "$status" -eq 0 ]
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
@test "update-upstream: SKILL.md O→KE prompt shares the workaround + scans issue comments for provenance (Directive 2/4)" {
|
|
296
|
-
# Directive 2 — a Known Error comment shares the WORKAROUND, not just root
|
|
297
|
-
# cause. Directive 4 — provenance: read ## Workaround AND scan the originating
|
|
298
|
-
# issue's body+comments (gh issue view --json comments,body) to attribute it.
|
|
299
|
-
run grep -F 'share it with correct PROVENANCE' "$SKILL_MD"
|
|
300
|
-
[ "$status" -eq 0 ]
|
|
301
|
-
run grep -F 'comments,body' "$SKILL_MD"
|
|
302
|
-
[ "$status" -eq 0 ]
|
|
303
|
-
run grep -F '## Workaround' "$SKILL_MD"
|
|
304
|
-
[ "$status" -eq 0 ]
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
@test "update-upstream: SKILL.md O→KE prompt names four provenance branches + credit shape + confirm-exact (Directive 4)" {
|
|
308
|
-
# The prompt must branch on who provided the workaround and credit per branch,
|
|
309
|
-
# always confirming the exact validated details.
|
|
310
|
-
run grep -F 'MAINTAINER-AUTHORED' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
311
|
-
run grep -F 'REPORTER-PROVIDED' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
312
|
-
run grep -F 'COMMENTER-PROVIDED' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
313
|
-
run grep -F 'BOTH-SOURCE' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
314
|
-
run grep -iE 'credit the reporter|credit them by @handle|credit.*both' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
315
|
-
run grep -iE 'CONFIRM THE EXACT|Confirmed the details|confirm the details' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
@test "update-upstream: SKILL.md inbound anti-leakage is visibility-gated — PUBLIC titled+linked, PRIVATE strict ban (Directive 3)" {
|
|
319
|
-
# Directive 3 — for PUBLIC repos refer to problems/ADRs/RFCs by title AND link
|
|
320
|
-
# (never bare ID); for PRIVATE/INTERNAL/indeterminate fall back to strict ban.
|
|
321
|
-
run grep -F 'gh repo view --json visibility' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
322
|
-
run grep -iE 'title AND as a link|titled\+linked' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
323
|
-
run grep -iE 'PRIVATE / INTERNAL / indeterminate|strict ban' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
324
|
-
# classification tokens / step IDs / internal vocab stay banned regardless.
|
|
325
|
-
run grep -iE 'Always banned' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
326
|
-
# grounded in ADR-055's permalink-progressive-enhancement.
|
|
327
|
-
run grep -F 'ADR-055' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
@test "update-upstream: SKILL.md inbound gate chain rides cog-a11y first (when-available, P338-gated, do-not-block)" {
|
|
331
|
-
# Directive 1's "run cog-a11y, risk, voice and tone" — cog-a11y rides FIRST,
|
|
332
|
-
# gated on P338 (plugin not yet shipped); the chain degrades to the dual gate
|
|
333
|
-
# today and does NOT block on P338.
|
|
334
|
-
run grep -iE 'cog-a11y → risk → voice-tone|cognitive-accessibility → external-comms' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
335
|
-
run grep -F 'P338' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
336
|
-
run grep -iE 'do NOT block|when-available' "$SKILL_MD"; [ "$status" -eq 0 ]
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
@test "transition-problem + manage-problem Step 7 greps match the inbound Origin alternation in LOCKSTEP (P363/P362)" {
|
|
340
|
-
# Both lockstep pre-checks must match ^## Reported Upstream OR
|
|
341
|
-
# ^\*\*Origin\*\*: inbound-reported \(# — drift re-opens the P363 gap on
|
|
342
|
-
# whichever surface lacks the alternation (ADR-010 copy-not-move / P362).
|
|
343
|
-
run grep -F 'inbound-reported \(#' "$TRANSITION_MD"
|
|
344
|
-
[ "$status" -eq 0 ]
|
|
345
|
-
run grep -F 'inbound-reported \(#' "$MANAGE_MD"
|
|
346
|
-
[ "$status" -eq 0 ]
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
# ─── Paired promptfoo eval (ADR-075 Amendment 2026-06-02) ────────────────────
|
|
350
|
-
#
|
|
351
|
-
# The paired promptfoo eval at packages/itil/skills/update-upstream/eval/
|
|
352
|
-
# discharges the R009 prose-floor for this SKILL surface atomically per
|
|
353
|
-
# ADR-075 evidence floor.
|
|
354
|
-
|
|
355
|
-
@test "update-upstream: paired promptfoo eval config exists (ADR-075 Amendment 2026-06-02)" {
|
|
356
|
-
[ -f "$EVAL_CONFIG" ]
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
@test "update-upstream: paired eval uses exec:bash provider per ADR-075 §6 (no API key)" {
|
|
360
|
-
# ADR-075 §6 — subscription auth via claude -p, no ANTHROPIC_API_KEY.
|
|
361
|
-
# The provider must be exec:bash invoking ./run-skill-eval.sh.
|
|
362
|
-
run grep -F "exec:bash ./run-skill-eval.sh" "$EVAL_CONFIG"
|
|
363
|
-
[ "$status" -eq 0 ]
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
@test "update-upstream: paired eval ships Tier-B llm-rubric grader for negative clauses" {
|
|
367
|
-
# Negative clauses (must NOT halt; must NOT invent) cannot be Tier-A
|
|
368
|
-
# graded — a not-regex for "halt" false-fails the correct "does NOT halt".
|
|
369
|
-
# The grader script + llm-rubric assertions discharge those clauses.
|
|
370
|
-
GRADER="$REPO_ROOT/packages/itil/skills/update-upstream/eval/grade-llm-rubric.sh"
|
|
371
|
-
[ -f "$GRADER" ]
|
|
372
|
-
[ -x "$GRADER" ]
|
|
373
|
-
run grep -F 'llm-rubric' "$EVAL_CONFIG"
|
|
374
|
-
[ "$status" -eq 0 ]
|
|
375
|
-
}
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bats
|
|
2
|
-
# Contract assertions for /wr-itil:work-problem (P071 split slice 3).
|
|
3
|
-
#
|
|
4
|
-
# This skill hosts the "pick the highest-WSJF ticket and work it" user
|
|
5
|
-
# intent previously hidden behind /wr-itil:manage-problem work. Unlike
|
|
6
|
-
# the plural orchestrator (/wr-itil:work-problems — batch AFK loop),
|
|
7
|
-
# this singular skill runs exactly one ticket per invocation and fires
|
|
8
|
-
# the AskUserQuestion selection prompt in interactive mode. Execution
|
|
9
|
-
# is delegated to /wr-itil:manage-problem <NNN> to avoid forking the
|
|
10
|
-
# per-ticket workflow.
|
|
11
|
-
#
|
|
12
|
-
# Structural assertion — Permitted Exception to the source-grep ban
|
|
13
|
-
# (ADR-005 / P011 / ADR-037 contract-assertion pattern).
|
|
14
|
-
#
|
|
15
|
-
# tdd-review: structural-permitted (justification: SKILL.md prose contract
|
|
16
|
-
# assertions; behavioural skill-runtime harness pending P012 + P081 Phase 2;
|
|
17
|
-
# expected to migrate to behavioural form once the harness exists. Touched
|
|
18
|
-
# during P136 Phase 2 ADR-044 alignment audit per the inline plan's
|
|
19
|
-
# bridge-marker rule.)
|
|
20
|
-
#
|
|
21
|
-
# @problem P071 (originating split)
|
|
22
|
-
# @problem P136 (ADR-044 alignment audit master — Phase 2 work-problem singular)
|
|
23
|
-
# @adr ADR-044 (Decision-Delegation Contract — framework-mediated Prioritisation surface)
|
|
24
|
-
# @jtbd JTBD-001 (enforce governance without slowing down — discoverable surface)
|
|
25
|
-
# @jtbd JTBD-101 (extend the suite with clear patterns — one skill per distinct user intent)
|
|
26
|
-
# @jtbd JTBD-201 (audit trail — selection cites the deciding tie-break rung)
|
|
27
|
-
#
|
|
28
|
-
# Cross-reference:
|
|
29
|
-
# P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
|
|
30
|
-
# P136: docs/problems/136-adr-044-alignment-audit-master.open.md
|
|
31
|
-
# ADR-010 amended (Skill Granularity section) — split naming + forwarder contract
|
|
32
|
-
# ADR-013 amended Rule 1 — structured user interaction; framework-resolution narrowing per ADR-044
|
|
33
|
-
# ADR-013 Rule 6 — AFK non-interactive fallback (Step 4 scope-expansion only)
|
|
34
|
-
# ADR-014 — governance skills commit their own work (delegated target owns commits)
|
|
35
|
-
# ADR-032 — governance skill invocation patterns (plural orchestrator delegates here)
|
|
36
|
-
# ADR-037 — contract-assertion bats pattern
|
|
37
|
-
# ADR-044 — Decision-Delegation Contract; Step 2 selection is framework-mediated
|
|
38
|
-
|
|
39
|
-
setup() {
|
|
40
|
-
SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
41
|
-
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@test "SKILL.md exists and has frontmatter" {
|
|
45
|
-
[ -f "$SKILL_FILE" ]
|
|
46
|
-
run head -1 "$SKILL_FILE"
|
|
47
|
-
[ "$status" -eq 0 ]
|
|
48
|
-
[ "$output" = "---" ]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
@test "SKILL.md frontmatter name is wr-itil:work-problem (singular, P071 + ADR-010 amended)" {
|
|
52
|
-
# Split naming convention per ADR-010 amendment: <verb>-<object>.
|
|
53
|
-
# CRITICAL: singular "work-problem", NOT plural "work-problems" — the
|
|
54
|
-
# plural name is reserved for the AFK orchestrator that already exists.
|
|
55
|
-
# Name coexistence is a P071 acknowledged trade-off.
|
|
56
|
-
run grep -n "^name: wr-itil:work-problem$" "$SKILL_FILE"
|
|
57
|
-
[ "$status" -eq 0 ]
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
@test "SKILL.md frontmatter name is NOT wr-itil:work-problems (regression guard for name collision)" {
|
|
61
|
-
# Guard against the easy slip of renaming this skill to match the
|
|
62
|
-
# plural orchestrator. If the name drifts to plural, `/wr-itil:`
|
|
63
|
-
# autocomplete shows two plural-looking skills side by side and users
|
|
64
|
-
# cannot tell which is interactive vs batch.
|
|
65
|
-
run grep -n "^name: wr-itil:work-problems$" "$SKILL_FILE"
|
|
66
|
-
[ "$status" -ne 0 ]
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
@test "SKILL.md frontmatter description names the pick-and-run intent (P071)" {
|
|
70
|
-
# Description must name "pick" / "work" / "highest-WSJF" so Claude
|
|
71
|
-
# Code autocomplete surfaces the user intent rather than a generic
|
|
72
|
-
# name. Also must mention "singular" or distinguish from the plural
|
|
73
|
-
# orchestrator so users pick the right one.
|
|
74
|
-
run grep -inE "^description:.*(pick|highest.wsjf|work.*problem)" "$SKILL_FILE"
|
|
75
|
-
[ "$status" -eq 0 ]
|
|
76
|
-
run grep -inE "^description:.*(singular|one ticket|distinct from.*work-problems)" "$SKILL_FILE"
|
|
77
|
-
[ "$status" -eq 0 ]
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
@test "SKILL.md frontmatter allowed-tools includes AskUserQuestion (selection prompt)" {
|
|
81
|
-
# Step 2 fires AskUserQuestion for the selection in interactive mode
|
|
82
|
-
# (ADR-013 Rule 1). Without the tool the structured-interaction
|
|
83
|
-
# contract cannot hold.
|
|
84
|
-
run grep -nE "^allowed-tools:.*AskUserQuestion" "$SKILL_FILE"
|
|
85
|
-
[ "$status" -eq 0 ]
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@test "SKILL.md frontmatter allowed-tools includes Skill (delegation to manage-problem + review-problems)" {
|
|
89
|
-
# Step 1 delegates the cache refresh to /wr-itil:review-problems when
|
|
90
|
-
# stale; Step 3 delegates the per-ticket execution to
|
|
91
|
-
# /wr-itil:manage-problem <NNN>. Both use the Skill tool per ADR-010's
|
|
92
|
-
# thin-router discipline.
|
|
93
|
-
run grep -nE "^allowed-tools:.*Skill" "$SKILL_FILE"
|
|
94
|
-
[ "$status" -eq 0 ]
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
@test "SKILL.md documents the singular-vs-plural naming distinction (P071 coexistence)" {
|
|
98
|
-
# The most common user confusion will be work-problem vs
|
|
99
|
-
# work-problems. The SKILL.md must name the distinction explicitly
|
|
100
|
-
# so `/wr-itil:` autocomplete readers can tell them apart. Without
|
|
101
|
-
# this, users will pick the wrong one and either run a single ticket
|
|
102
|
-
# when they wanted the AFK loop or vice-versa.
|
|
103
|
-
run grep -inE "work-problems.*plural|plural.*work-problems|AFK orchestrator" "$SKILL_FILE"
|
|
104
|
-
[ "$status" -eq 0 ]
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
@test "SKILL.md delegates execution to /wr-itil:manage-problem (anti-fork discipline)" {
|
|
108
|
-
# Per ADR-010 thin-router: the split skill owns selection, NOT
|
|
109
|
-
# execution. The per-ticket investigate/transition/fix/release flow
|
|
110
|
-
# stays on /wr-itil:manage-problem <NNN>. If this skill re-implements
|
|
111
|
-
# the execution inline, the deprecation window hardens into a
|
|
112
|
-
# permanent fork.
|
|
113
|
-
run grep -inE "/wr-itil:manage-problem" "$SKILL_FILE"
|
|
114
|
-
[ "$status" -eq 0 ]
|
|
115
|
-
run grep -inE "delegate.*manage-problem|Skill tool.*manage-problem|manage-problem.*Skill tool" "$SKILL_FILE"
|
|
116
|
-
[ "$status" -eq 0 ]
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
@test "SKILL.md defers README.md cache refresh to /wr-itil:review-problems (P062 ownership)" {
|
|
120
|
-
# P062 makes /wr-itil:review-problems the canonical README.md cache
|
|
121
|
-
# writer. This skill reads the cache but must NOT rewrite it —
|
|
122
|
-
# re-implementing the refresh here would break the one-canonical-
|
|
123
|
-
# writer invariant.
|
|
124
|
-
run grep -inE "/wr-itil:review-problems" "$SKILL_FILE"
|
|
125
|
-
[ "$status" -eq 0 ]
|
|
126
|
-
run grep -inE "(delegate|defer|refresh).*review-problems|review-problems.*(refresh|delegate|defer)" "$SKILL_FILE"
|
|
127
|
-
[ "$status" -eq 0 ]
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
@test "SKILL.md reads README.md cache via the git-history freshness test (P031)" {
|
|
131
|
-
# Same freshness check as list-problems and review-problems — mtime
|
|
132
|
-
# is unreliable in worktrees per P031. Drift here means false
|
|
133
|
-
# cache-hit (serving a stale ranking) or false cache-miss (spamming
|
|
134
|
-
# review refreshes).
|
|
135
|
-
run grep -inE "docs/problems/README\.md" "$SKILL_FILE"
|
|
136
|
-
[ "$status" -eq 0 ]
|
|
137
|
-
run grep -inE "git log.*--format.*README\.md|readme_commit" "$SKILL_FILE"
|
|
138
|
-
[ "$status" -eq 0 ]
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
@test "SKILL.md fires the AskUserQuestion selection prompt (ADR-013 Rule 1)" {
|
|
142
|
-
# Step 2 is the structured-interaction path: single top-WSJF ticket
|
|
143
|
-
# shown as Recommended, or tied tickets shown as peer options. Never
|
|
144
|
-
# prose "(a)/(b)/(c)".
|
|
145
|
-
run grep -inE "AskUserQuestion" "$SKILL_FILE"
|
|
146
|
-
[ "$status" -eq 0 ]
|
|
147
|
-
run grep -inE "Next problem|Recommended|tied" "$SKILL_FILE"
|
|
148
|
-
[ "$status" -eq 0 ]
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
@test "SKILL.md forbids prose selection fallback (P053 + ADR-013 Rule 1 regression guard)" {
|
|
152
|
-
# Prose "which would you like?" or "(a)/(b)/(c)" is the anti-pattern
|
|
153
|
-
# ADR-013 Rule 1 and P053 codify against. The SKILL.md must say
|
|
154
|
-
# "never" so the contract is legible at the spec level.
|
|
155
|
-
run grep -inE "never.*prose|never.*\(a\)/\(b\)" "$SKILL_FILE"
|
|
156
|
-
[ "$status" -eq 0 ]
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
@test "SKILL.md documents the AFK non-interactive branch (ADR-013 Rule 6)" {
|
|
160
|
-
# When /wr-itil:work-problems invokes this skill inside an AFK
|
|
161
|
-
# subagent iteration, AskUserQuestion is unavailable — the selection
|
|
162
|
-
# has already happened at the orchestrator level. The skill must
|
|
163
|
-
# degrade gracefully per Rule 6.
|
|
164
|
-
run grep -inE "AFK|non-interactive|ADR-013 Rule 6|Rule 6" "$SKILL_FILE"
|
|
165
|
-
[ "$status" -eq 0 ]
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
@test "SKILL.md documents the scope-expansion AskUserQuestion (3-option shape)" {
|
|
169
|
-
# Effort drift during investigation or architect review must fire the
|
|
170
|
-
# standard Continue / Re-rank / Pick-different three-option prompt,
|
|
171
|
-
# same as /wr-itil:manage-problem's Working a Problem section.
|
|
172
|
-
run grep -inE "Scope change|scope.expansion" "$SKILL_FILE"
|
|
173
|
-
[ "$status" -eq 0 ]
|
|
174
|
-
run grep -inE "Continue with expanded scope|Update problem and re-rank|Pick a different problem" "$SKILL_FILE"
|
|
175
|
-
[ "$status" -eq 0 ]
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
@test "SKILL.md runs exactly one ticket per invocation (singular contract)" {
|
|
179
|
-
# The whole point of the singular skill: one ticket, then stop. The
|
|
180
|
-
# SKILL.md must say "do not loop automatically" or equivalent so the
|
|
181
|
-
# contract is explicit. Looping is the plural orchestrator's job.
|
|
182
|
-
run grep -inE "do not loop automatically|one ticket per invocation|singular" "$SKILL_FILE"
|
|
183
|
-
[ "$status" -eq 0 ]
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
@test "SKILL.md does not carry a deprecated-arguments frontmatter flag (clean-split skill)" {
|
|
187
|
-
# Architect advisory: work-problem is a clean-split skill with no
|
|
188
|
-
# argument-subcommands itself. ADR-010 amendment's
|
|
189
|
-
# `deprecated-arguments: true` flag is only valid on host skills with
|
|
190
|
-
# forwarder routes — work-problem is a forwarder TARGET, not a host.
|
|
191
|
-
run grep -E "^deprecated-arguments:" "$SKILL_FILE"
|
|
192
|
-
[ "$status" -ne 0 ]
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
@test "SKILL.md does not use word-argument subcommand branching (P071 regression guard)" {
|
|
196
|
-
# The whole point of P071: Claude Code autocomplete does not surface
|
|
197
|
-
# arguments. A clean-split skill must not reintroduce word-arg
|
|
198
|
-
# subcommand routing.
|
|
199
|
-
run grep -inE "If arguments start with|If arguments contain" "$SKILL_FILE"
|
|
200
|
-
[ "$status" -ne 0 ]
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
@test "SKILL.md cites P071 and ADR-010 amended (traceability per ADR-037)" {
|
|
204
|
-
# ADR-037 traceability: the skill spec cites the problem it closes
|
|
205
|
-
# and the ADR that authorises the split.
|
|
206
|
-
run grep -inE "P071|ADR-010" "$SKILL_FILE"
|
|
207
|
-
[ "$status" -eq 0 ]
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
@test "SKILL.md cites ADR-032 + P077 (AFK orchestrator delegation target)" {
|
|
211
|
-
# /wr-itil:work-problems Step 5 delegates iterations via the Agent
|
|
212
|
-
# tool (P077). This skill is the execution unit those iterations
|
|
213
|
-
# invoke. The cross-reference documents the pair relationship so
|
|
214
|
-
# future drift to /wr-itil:work-problems doesn't orphan this skill.
|
|
215
|
-
run grep -inE "P077|ADR-032" "$SKILL_FILE"
|
|
216
|
-
[ "$status" -eq 0 ]
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
# ----------------------------------------------------------------------
|
|
220
|
-
# P136 Phase 2 — ADR-044 alignment audit (added 2026-04-27)
|
|
221
|
-
#
|
|
222
|
-
# These assertions land the framework-mediated-selection contract for
|
|
223
|
-
# Step 2 and the ADR-044 category-2 cross-reference for Step 4. They
|
|
224
|
-
# replace the prior assertions that mandated AskUserQuestion-driven
|
|
225
|
-
# selection (which was the lazy-deferral surface ADR-044 was written to
|
|
226
|
-
# close).
|
|
227
|
-
# ----------------------------------------------------------------------
|
|
228
|
-
|
|
229
|
-
@test "SKILL.md Step 2 specifies framework-mediated selection (ADR-044 Prioritisation)" {
|
|
230
|
-
# Per ADR-044 Framework-Mediated Surface row "Prioritisation — WSJF
|
|
231
|
-
# formula + documented tie-breaks (Known Error > Open; smaller effort
|
|
232
|
-
# first; older reported date). Pick + work." Step 2 must apply the
|
|
233
|
-
# tie-break ladder mechanically rather than defer to AskUserQuestion.
|
|
234
|
-
run awk '/^### 2\./,/^### 3\./' "$SKILL_FILE"
|
|
235
|
-
[ "$status" -eq 0 ]
|
|
236
|
-
[[ "$output" == *"framework-mediated"* ]] || [[ "$output" == *"tie-break ladder"* ]]
|
|
237
|
-
[[ "$output" == *"Known Error"* ]]
|
|
238
|
-
[[ "$output" == *"smaller"* ]]
|
|
239
|
-
[[ "$output" == *"older reported date"* ]]
|
|
240
|
-
[[ "$output" == *"ADR-044"* ]]
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
@test "SKILL.md Step 2 reports the chosen ticket + tie-break rung that decided (JTBD-201 audit-trail)" {
|
|
244
|
-
# Audit-trail outcome: the agent must cite which rung of the ladder
|
|
245
|
-
# decided the selection so the choice is reproducible from the README
|
|
246
|
-
# state at the time of the report.
|
|
247
|
-
run awk '/^### 2\./,/^### 3\./' "$SKILL_FILE"
|
|
248
|
-
[ "$status" -eq 0 ]
|
|
249
|
-
[[ "$output" == *"report"* ]]
|
|
250
|
-
[[ "$output" == *"tie-break"* ]] || [[ "$output" == *"ladder rung"* ]]
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
@test "SKILL.md Step 2 documents user-override path via direct NNN invocation" {
|
|
254
|
-
# Selection is framework-mediated, but the user retains agency via
|
|
255
|
-
# /wr-itil:work-problem <NNN> direct invocation. Without the
|
|
256
|
-
# documented escape hatch, the user has no way to redirect except via
|
|
257
|
-
# post-hoc correction (ADR-044 category 6). The literal-form
|
|
258
|
-
# assertion guards against the substring trap where /wr-itil:work-
|
|
259
|
-
# problems (plural) accidentally satisfies a /wr-itil:work-problem
|
|
260
|
-
# substring check.
|
|
261
|
-
run awk '/^### 2\./,/^### 3\./' "$SKILL_FILE"
|
|
262
|
-
[ "$status" -eq 0 ]
|
|
263
|
-
[[ "$output" == *"/wr-itil:work-problem <NNN>"* ]] || [[ "$output" == *"/wr-itil:work-problem <ID>"* ]] || [[ "$output" == *"\`/wr-itil:work-problem 042\`"* ]]
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
@test "SKILL.md Step 2 does NOT fire AskUserQuestion as the selection mechanism (regression guard)" {
|
|
267
|
-
# The AskUserQuestion-driven selection prompt was the lazy-deferral
|
|
268
|
-
# surface ADR-044 closed. If it returns to Step 2 the lazy-count
|
|
269
|
-
# metric (Step 2d "Ask Hygiene Pass") will spike. AskUserQuestion may
|
|
270
|
-
# appear elsewhere (Step 4 scope-expansion) but NOT inside Step 2.
|
|
271
|
-
run awk '/^### 2\./,/^### 3\./' "$SKILL_FILE"
|
|
272
|
-
[ "$status" -eq 0 ]
|
|
273
|
-
! echo "$output" | grep -qE "Selection via .?AskUserQuestion|Use .header: .Next problem"
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
@test "SKILL.md Step 4 cross-references ADR-044 category-2 (deviation-approval)" {
|
|
277
|
-
# Effort growth IS the contradicting evidence against the WSJF score
|
|
278
|
-
# that ranked this ticket at the top — it's a deviation-approval
|
|
279
|
-
# surface in the ADR-044 taxonomy. The inline cross-reference makes
|
|
280
|
-
# the framework-resolution boundary visible at the call site.
|
|
281
|
-
run awk '/^### 4\./,/^### 5\./' "$SKILL_FILE"
|
|
282
|
-
[ "$status" -eq 0 ]
|
|
283
|
-
[[ "$output" == *"ADR-044"* ]]
|
|
284
|
-
[[ "$output" == *"deviation-approval"* ]] || [[ "$output" == *"category 2"* ]] || [[ "$output" == *"category-2"* ]]
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
@test "bats file carries the tdd-review: structural-permitted marker (P081 + P136 bridge)" {
|
|
288
|
-
# Per P136 Phase 2 inline plan: bats touched during the audit get
|
|
289
|
-
# the structural-permitted marker as the bridge until P081 Phase 2's
|
|
290
|
-
# canonical retrofit. Without the marker, future TDD agent reviews
|
|
291
|
-
# will flag the file as a P081 violation.
|
|
292
|
-
run grep -nE "tdd-review:[[:space:]]+structural-permitted" "${BATS_TEST_FILENAME}"
|
|
293
|
-
[ "$status" -eq 0 ]
|
|
294
|
-
}
|