@windyroad/itil 0.11.0-preview.148 → 0.12.0-preview.150
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 +1 -1
- package/skills/manage-problem/SKILL.md +20 -3
- package/skills/manage-problem/test/manage-problem-transition-forwarder.bats +96 -0
- package/skills/manage-problem/test/manage-problem-work-forwarder.bats +88 -0
- package/skills/transition-problem/SKILL.md +133 -0
- package/skills/transition-problem/test/transition-problem-contract.bats +175 -0
- package/skills/work-problem/SKILL.md +130 -0
- package/skills/work-problem/test/work-problem-contract.bats +206 -0
package/package.json
CHANGED
|
@@ -125,9 +125,10 @@ What "work" means depends on the problem's status:
|
|
|
125
125
|
### 1. Parse the request
|
|
126
126
|
|
|
127
127
|
Determine the operation from `$ARGUMENTS`:
|
|
128
|
-
- If arguments start with a number (e.g., "011")
|
|
128
|
+
- If arguments start with a number (e.g., "011") **followed by a status word** (`known-error`, `verifying`, or `close`), **delegate to `/wr-itil:transition-problem`** via the Skill tool. See "Deprecated-argument forwarders" below.
|
|
129
|
+
- If arguments start with a bare number (e.g., "011" with no status word after it), this is an update flow — handled inline by the ticket-body edit steps (Step 6).
|
|
129
130
|
- If arguments contain "list", **delegate to `/wr-itil:list-problems`** via the Skill tool. See "Deprecated-argument forwarders" below.
|
|
130
|
-
- If arguments contain "work",
|
|
131
|
+
- If arguments contain "work", **delegate to `/wr-itil:work-problem`** via the Skill tool. See "Deprecated-argument forwarders" below.
|
|
131
132
|
- If arguments contain "review", **delegate to `/wr-itil:review-problems`** via the Skill tool. See "Deprecated-argument forwarders" below.
|
|
132
133
|
- Otherwise, this is a new problem creation
|
|
133
134
|
|
|
@@ -151,7 +152,23 @@ When `$ARGUMENTS` contains the word `review` as a top-level argument (not inside
|
|
|
151
152
|
|
|
152
153
|
The forwarder does NOT re-implement the review logic locally — it invokes the Skill tool with `wr-itil:review-problems` and returns the new skill's output verbatim. Duplicating the Step 9 re-scoring / auto-transition / verification-prompt / README-refresh stack would harden the deprecation window into a permanent fork.
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
**Forwarder for `work`** (P071 split slice 3 — new skill `/wr-itil:work-problem`, singular):
|
|
156
|
+
|
|
157
|
+
When `$ARGUMENTS` contains the word `work` as a top-level argument (not inside a ticket body edit), delegate to `/wr-itil:work-problem` via the Skill tool and emit this systemMessage verbatim:
|
|
158
|
+
|
|
159
|
+
> `/wr-itil:manage-problem work is deprecated; use /wr-itil:work-problem directly. This forwarder will be removed in @windyroad/itil's next major version.`
|
|
160
|
+
|
|
161
|
+
The forwarder does NOT re-implement the selection logic locally — it invokes the Skill tool with `wr-itil:work-problem` and returns the new skill's output verbatim. Duplicating the freshness-check / AskUserQuestion selection / delegate-to-`manage-problem <NNN>` stack would harden the deprecation window into a permanent fork. Note the singular/plural distinction: the forwarder targets `/wr-itil:work-problem` (singular, one ticket per invocation), NOT `/wr-itil:work-problems` (plural AFK orchestrator). The two names coexist intentionally per P071.
|
|
162
|
+
|
|
163
|
+
**Forwarder for `<NNN> <status>` transitions** (P071 split slice 4 — new skill `/wr-itil:transition-problem`):
|
|
164
|
+
|
|
165
|
+
When `$ARGUMENTS` starts with a three-digit ticket ID followed by a status word (`known-error`, `verifying`, or `close`), delegate to `/wr-itil:transition-problem` via the Skill tool and emit the canonical deprecation notice verbatim, naming the specific argument form the user supplied:
|
|
166
|
+
|
|
167
|
+
> `/wr-itil:manage-problem <NNN> <status> is deprecated; use /wr-itil:transition-problem <NNN> <status> directly. This forwarder will be removed in @windyroad/itil's next major version.`
|
|
168
|
+
|
|
169
|
+
The parser must distinguish a **bare `<NNN>`** (update flow — handled inline by Step 6) from a **`<NNN> <status>` pair** (transition — delegated). The status-word tokens that trigger the transition forwarder are fixed: `known-error`, `verifying`, `close`. Any other suffix after `<NNN>` routes to the inline update flow per Step 6. This preserves the two legitimate shapes the original subcommand carried while splitting the transition intent out cleanly.
|
|
170
|
+
|
|
171
|
+
The forwarder does NOT re-implement the Step 7 transition logic locally — it invokes the Skill tool with `wr-itil:transition-problem` and returns the new skill's output verbatim. Duplicating the pre-flight-checks / P063-external-root-cause-detection / P057-staging-trap / P062-README-refresh stack would harden the deprecation window into a permanent fork. The delegated `/wr-itil:transition-problem` skill then re-invokes `/wr-itil:manage-problem <NNN> <status>` to run the authoritative Step 7 block — but routed through the clean-split skill's data-parameter contract, not the deprecated subcommand path. Lifecycle completeness (known-error + verifying + close) is covered per ADR-022's three-status mandate.
|
|
155
172
|
|
|
156
173
|
### 2. For new problems: Check for duplicates FIRST
|
|
157
174
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Contract assertions for manage-problem's `<NNN> <status>` transition forwarder (P071 split slice 4).
|
|
3
|
+
#
|
|
4
|
+
# Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
|
|
5
|
+
# `/wr-itil:manage-problem <NNN> known-error` (and the sibling close
|
|
6
|
+
# form) delegates to the new `/wr-itil:transition-problem` skill via
|
|
7
|
+
# a thin-router forwarder. Original skill already carries
|
|
8
|
+
# `deprecated-arguments: true` frontmatter from slice 1; this file
|
|
9
|
+
# asserts the transition-forwarder-specific contract.
|
|
10
|
+
#
|
|
11
|
+
# Note on shape: the transition forwarders are the trickiest of the
|
|
12
|
+
# P071 phased set because the argument is `<NNN> <word>` (data +
|
|
13
|
+
# verb). The parser must route on the PRESENCE of the verb token
|
|
14
|
+
# (`known-error` / `verifying` / `close`) AFTER the data parameter
|
|
15
|
+
# `<NNN>`. A bare `<NNN>` remains the legitimate update flow — it
|
|
16
|
+
# must NOT forward. This test locks the distinction in.
|
|
17
|
+
#
|
|
18
|
+
# Structural assertion — Permitted Exception to the source-grep ban
|
|
19
|
+
# (ADR-005 / P011 / ADR-037 contract-assertion pattern).
|
|
20
|
+
#
|
|
21
|
+
# @problem P071
|
|
22
|
+
# @jtbd JTBD-001 (enforce governance without slowing down)
|
|
23
|
+
# @jtbd JTBD-101 (extend the suite with clear patterns)
|
|
24
|
+
#
|
|
25
|
+
# Cross-reference:
|
|
26
|
+
# P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
|
|
27
|
+
# ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
|
|
28
|
+
# ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
|
|
29
|
+
# ADR-022 — Verification Pending is a first-class status; .verifying.md suffix on release
|
|
30
|
+
# ADR-037 — contract-assertion bats pattern
|
|
31
|
+
|
|
32
|
+
setup() {
|
|
33
|
+
SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
34
|
+
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@test "manage-problem Step 1 forwards '<NNN> known-error' argument to /wr-itil:transition-problem (P071 slice 4)" {
|
|
38
|
+
# The forwarder names the target skill explicitly so the router is
|
|
39
|
+
# legible at the contract level. ADR-010's canonical shape: "invokes
|
|
40
|
+
# the new named skill via the Skill tool, not via re-prompting the
|
|
41
|
+
# user".
|
|
42
|
+
run grep -inE "/wr-itil:transition-problem" "$SKILL_FILE"
|
|
43
|
+
[ "$status" -eq 0 ]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@test "manage-problem Step 1 emits the canonical known-error transition deprecation notice (ADR-010 amended)" {
|
|
47
|
+
# ADR-010's canonical deprecation-notice template:
|
|
48
|
+
# "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
|
|
49
|
+
# directly. This forwarder will be removed in <plugin>'s next major
|
|
50
|
+
# version."
|
|
51
|
+
# The notice MUST be emitted as a systemMessage (not AskUserQuestion)
|
|
52
|
+
# because deprecation is informational, not decisional (ADR-013
|
|
53
|
+
# Rule 1 scope). The transition-forwarder notice is distinct from
|
|
54
|
+
# list + review + work forwarders; all four must co-exist verbatim.
|
|
55
|
+
run grep -inE "is deprecated.*use /wr-itil:transition-problem|deprecated.*transition-problem|removed in .* next major version" "$SKILL_FILE"
|
|
56
|
+
[ "$status" -eq 0 ]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@test "manage-problem Step 1 transition-forwarder does not re-implement Step 7 transition logic (P071 regression guard)" {
|
|
60
|
+
# The forwarder must not duplicate the transition logic — it must
|
|
61
|
+
# delegate. Per ADR-010: "thin-router forwarder re-invokes the new
|
|
62
|
+
# named skill via the Skill tool". If the forwarder grows its own
|
|
63
|
+
# pre-flight + P057 + P063 + P062 stack, the deprecation window
|
|
64
|
+
# will harden into a permanent fork.
|
|
65
|
+
run grep -inE "delegate.*transition-problem|Skill tool.*transition-problem|transition-problem.*Skill tool" "$SKILL_FILE"
|
|
66
|
+
[ "$status" -eq 0 ]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@test "manage-problem Step 1 parser distinguishes bare <NNN> (update) from <NNN> <status> (transition)" {
|
|
70
|
+
# Critical safety rule: a bare `<NNN>` argument must REMAIN the
|
|
71
|
+
# update flow — it must not accidentally forward to
|
|
72
|
+
# transition-problem. Only the `<NNN> <status>` shape (where
|
|
73
|
+
# <status> ∈ {known-error, verifying, close}) triggers the
|
|
74
|
+
# transition forwarder. The parser block must name both branches
|
|
75
|
+
# so the distinction is legible at the contract level.
|
|
76
|
+
run grep -inE "known-error|verifying|close" "$SKILL_FILE"
|
|
77
|
+
[ "$status" -eq 0 ]
|
|
78
|
+
# And the bare-NNN update path is still documented.
|
|
79
|
+
run grep -inE "bare .NNN.|update flow|<NNN>.*update" "$SKILL_FILE"
|
|
80
|
+
[ "$status" -eq 0 ]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@test "manage-problem transition-forwarder covers known-error, verifying, and close (lifecycle completeness)" {
|
|
84
|
+
# ADR-022 codifies three transition destinations: known-error,
|
|
85
|
+
# verifying (Verification Pending), and closed. All three must
|
|
86
|
+
# appear in the forwarder contract so users can rely on the
|
|
87
|
+
# forwarder for the full lifecycle during the deprecation window.
|
|
88
|
+
# Missing any destination would force users back onto inline
|
|
89
|
+
# execution for that one case.
|
|
90
|
+
run grep -inE "known-error" "$SKILL_FILE"
|
|
91
|
+
[ "$status" -eq 0 ]
|
|
92
|
+
run grep -inE "verifying|verification.pending" "$SKILL_FILE"
|
|
93
|
+
[ "$status" -eq 0 ]
|
|
94
|
+
run grep -inE "\bclose\b" "$SKILL_FILE"
|
|
95
|
+
[ "$status" -eq 0 ]
|
|
96
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Contract assertions for manage-problem's `work` subcommand forwarder (P071 split slice 3).
|
|
3
|
+
#
|
|
4
|
+
# Per ADR-010 amended (Skill Granularity section) + P071 phased plan:
|
|
5
|
+
# `/wr-itil:manage-problem work` delegates to the new
|
|
6
|
+
# `/wr-itil:work-problem` (singular) skill via a thin-router forwarder.
|
|
7
|
+
# Original skill already carries `deprecated-arguments: true` frontmatter
|
|
8
|
+
# from slice 1; this file asserts the work-forwarder-specific contract.
|
|
9
|
+
#
|
|
10
|
+
# CRITICAL naming distinction: the forwarder target is singular
|
|
11
|
+
# `/wr-itil:work-problem` — NOT the plural `/wr-itil:work-problems`
|
|
12
|
+
# (the AFK orchestrator that already exists). Name coexistence is a
|
|
13
|
+
# P071-acknowledged trade-off.
|
|
14
|
+
#
|
|
15
|
+
# Structural assertion — Permitted Exception to the source-grep ban
|
|
16
|
+
# (ADR-005 / P011 / ADR-037 contract-assertion pattern).
|
|
17
|
+
#
|
|
18
|
+
# @problem P071
|
|
19
|
+
# @jtbd JTBD-001 (enforce governance without slowing down)
|
|
20
|
+
# @jtbd JTBD-101 (extend the suite with clear patterns)
|
|
21
|
+
#
|
|
22
|
+
# Cross-reference:
|
|
23
|
+
# P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
|
|
24
|
+
# ADR-010 amended — split naming + forwarder contract + deprecated-arguments flag
|
|
25
|
+
# ADR-013 Rule 1 — structured user interaction (forwarder emits systemMessage, not AskUserQuestion)
|
|
26
|
+
# ADR-037 — contract-assertion bats pattern
|
|
27
|
+
|
|
28
|
+
setup() {
|
|
29
|
+
SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
30
|
+
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@test "manage-problem Step 1 forwards 'work' argument to /wr-itil:work-problem singular (P071 slice 3)" {
|
|
34
|
+
# The forwarder names the target skill explicitly so the router is
|
|
35
|
+
# legible at the contract level. ADR-010's canonical shape: "invokes
|
|
36
|
+
# the new named skill via the Skill tool, not via re-prompting the
|
|
37
|
+
# user". Target is the SINGULAR name.
|
|
38
|
+
run grep -inE "/wr-itil:work-problem\b" "$SKILL_FILE"
|
|
39
|
+
[ "$status" -eq 0 ]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@test "manage-problem Step 1 work-forwarder target is singular, not plural (name collision guard)" {
|
|
43
|
+
# The forwarder target MUST be /wr-itil:work-problem (singular).
|
|
44
|
+
# The plural /wr-itil:work-problems already exists as the AFK
|
|
45
|
+
# orchestrator and has a completely different semantics (batch loop
|
|
46
|
+
# vs single ticket). A forwarder that routed 'work' to the plural
|
|
47
|
+
# orchestrator would subtly break interactive invocations — the user
|
|
48
|
+
# would get an AFK-mode iteration loop when they wanted one ticket.
|
|
49
|
+
#
|
|
50
|
+
# Assert the forwarder block explicitly names 'singular' so the
|
|
51
|
+
# distinction is legible at the contract level.
|
|
52
|
+
run grep -inE "/wr-itil:work-problem.*singular|singular.*work-problem" "$SKILL_FILE"
|
|
53
|
+
[ "$status" -eq 0 ]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@test "manage-problem Step 1 emits the canonical work deprecation notice (ADR-010 amended)" {
|
|
57
|
+
# ADR-010's canonical deprecation-notice template:
|
|
58
|
+
# "/wr-<plugin>:<old> <arg> is deprecated; use /wr-<plugin>:<new>
|
|
59
|
+
# directly. This forwarder will be removed in <plugin>'s next major
|
|
60
|
+
# version."
|
|
61
|
+
# The notice MUST be emitted as a systemMessage (not AskUserQuestion)
|
|
62
|
+
# because deprecation is informational, not decisional (ADR-013 Rule 1
|
|
63
|
+
# scope). Work-forwarder notice is distinct from list + review
|
|
64
|
+
# forwarders; all three must co-exist verbatim.
|
|
65
|
+
run grep -inE "is deprecated.*use /wr-itil:work-problem|deprecated.*work-problem|removed in .* next major version" "$SKILL_FILE"
|
|
66
|
+
[ "$status" -eq 0 ]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@test "manage-problem Step 1 work-forwarder does not re-implement selection logic (P071 regression guard)" {
|
|
70
|
+
# The forwarder must not duplicate the selection logic — it must
|
|
71
|
+
# delegate. Per ADR-010: "thin-router forwarder re-invokes the new
|
|
72
|
+
# named skill via the Skill tool". If the forwarder grows its own
|
|
73
|
+
# freshness-check + AskUserQuestion + delegate stack, the
|
|
74
|
+
# deprecation window will harden into a permanent fork.
|
|
75
|
+
run grep -inE "delegate.*work-problem\b|Skill tool.*work-problem\b|work-problem\b.*Skill tool" "$SKILL_FILE"
|
|
76
|
+
[ "$status" -eq 0 ]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@test "manage-problem work-forwarder Step 1 parser delegates, does not run inline (P071 slice 3)" {
|
|
80
|
+
# Slice 3's defining behaviour: Step 1's `work` branch must delegate,
|
|
81
|
+
# not run the review+select flow inline. The parser line must say
|
|
82
|
+
# "delegate to /wr-itil:work-problem", matching the shape the list
|
|
83
|
+
# and review forwarders use. A stale "run a review (step 9) first"
|
|
84
|
+
# line would indicate the forwarder was added without updating the
|
|
85
|
+
# parser (common slip per slice 2's lesson).
|
|
86
|
+
run grep -nE "^- If arguments contain \"work\", \*\*delegate to \`/wr-itil:work-problem\`\*\*" "$SKILL_FILE"
|
|
87
|
+
[ "$status" -eq 0 ]
|
|
88
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wr-itil:transition-problem
|
|
3
|
+
description: Advance a problem ticket's lifecycle status — Open → Known Error, Known Error → Verification Pending (verifying), Verification Pending → Closed. Renames the ticket file, updates the Status field, and refreshes docs/problems/README.md in the same commit. Delegates the execution to /wr-itil:manage-problem so the pre-flight checks, P057 staging-trap handling, P063 external-root-cause detection, and P062 README refresh stay on a single authoritative workflow. Use when the user asks to "transition", "close", "mark known-error", or "release" a specific ticket.
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Transition Problem — Lifecycle Advance
|
|
8
|
+
|
|
9
|
+
Advance a specific problem ticket along the ITIL lifecycle: Open → Known Error → Verification Pending → Closed. The skill is a **thin-router selection surface** — it identifies the ticket and the destination status, then delegates the actual transition execution to `/wr-itil:manage-problem <NNN>` (which hosts the authoritative Step 7 transition block). This preserves the single-workflow ownership of the pre-flight checks, external-root-cause detection (P063), staging-trap handling (P057), and README.md refresh (P062).
|
|
10
|
+
|
|
11
|
+
This skill is phase 4 of the P071 phased-landing split of `/wr-itil:manage-problem <NNN> <status>` per ADR-010's amended Skill Granularity rule (one skill per distinct user intent). The original `/wr-itil:manage-problem <NNN> known-error` subcommand route remains as a thin-router forwarder during the deprecation window but is scheduled for removal in `@windyroad/itil`'s next major version.
|
|
12
|
+
|
|
13
|
+
## Arguments
|
|
14
|
+
|
|
15
|
+
- `<NNN>` — the ticket ID (data parameter, e.g. `042`). Required.
|
|
16
|
+
- `<status>` — the destination status. One of:
|
|
17
|
+
- `known-error` — Open → Known Error (root cause confirmed, fix path clear, fix not yet released).
|
|
18
|
+
- `verifying` — Known Error → Verification Pending (fix released, awaiting user verification per ADR-022).
|
|
19
|
+
- `close` — Verification Pending → Closed (user has confirmed the fix works in production).
|
|
20
|
+
|
|
21
|
+
The `<NNN>` and `<status>` tokens are **data parameters**, not word-subcommands. Per the P071 split rule (ADR-010 amended), data parameters (IDs, paths, URLs, enum destinations) are permitted; word-subcommands that name distinct user intents are not. This skill's argument shape is `data + data`, which is the same shape as `/wr-itil:report-upstream <NNN>`.
|
|
22
|
+
|
|
23
|
+
## Scope
|
|
24
|
+
|
|
25
|
+
**In scope:**
|
|
26
|
+
- Validate that the ticket file exists and the destination status is reachable from the current status (e.g. an `.open.md` file cannot transition directly to Verification Pending — it must go through Known Error first).
|
|
27
|
+
- Delegate the transition execution to `/wr-itil:manage-problem <NNN> <status>` via the Skill tool so the full Step 7 block runs (pre-flight checks, external-root-cause detection, file rename, Status field edit, staging re-stage per P057, README.md refresh per P062, commit per ADR-014).
|
|
28
|
+
- Report the outcome (new filename, new Status, commit SHA).
|
|
29
|
+
|
|
30
|
+
**Out of scope:**
|
|
31
|
+
- Re-implementing the Step 7 transition logic inline. Delegation to `/wr-itil:manage-problem` is the anti-fork discipline.
|
|
32
|
+
- Backlog re-ranking — that's `/wr-itil:review-problems`.
|
|
33
|
+
- Ticket creation or bare-update flows — that's `/wr-itil:manage-problem` (no-args form for creation, `<NNN>` bare for update).
|
|
34
|
+
- Parking a ticket — that's a distinct lifecycle move handled by `/wr-itil:manage-problem` directly (the `.parked.md` suffix has its own pre-flight path including P063 external-root-cause detection for `upstream-blocked` reasons).
|
|
35
|
+
|
|
36
|
+
## Steps
|
|
37
|
+
|
|
38
|
+
### 1. Parse the arguments
|
|
39
|
+
|
|
40
|
+
From `$ARGUMENTS`, extract the ticket ID (`<NNN>`, three digits) and the destination status (one of `known-error`, `verifying`, `close`). If either is missing or malformed, emit a usage message and stop:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Usage: /wr-itil:transition-problem <NNN> <status>
|
|
44
|
+
<NNN> — three-digit ticket ID (e.g. 042)
|
|
45
|
+
<status> — one of: known-error, verifying, close
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Discover the ticket file
|
|
49
|
+
|
|
50
|
+
Locate the ticket file by ID:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
ls docs/problems/<NNN>-*.md 2>/dev/null
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If no file is found, emit: `No ticket found for ID <NNN>` and stop.
|
|
57
|
+
|
|
58
|
+
If multiple files are found (should not happen — suffix-exclusive lifecycle), emit a warning and list the matches; stop and let the user resolve.
|
|
59
|
+
|
|
60
|
+
### 3. Validate the transition path
|
|
61
|
+
|
|
62
|
+
Check the current filename suffix and verify the destination status is reachable in one step:
|
|
63
|
+
|
|
64
|
+
| Current suffix | Destination argument | Valid? |
|
|
65
|
+
|----------------|----------------------|--------|
|
|
66
|
+
| `.open.md` | `known-error` | yes |
|
|
67
|
+
| `.known-error.md` | `verifying` | yes |
|
|
68
|
+
| `.verifying.md` | `close` | yes |
|
|
69
|
+
| any other pairing | — | no — emit an error and stop |
|
|
70
|
+
|
|
71
|
+
If the pairing is invalid, emit a clear message naming the current status, the requested destination, and the valid next step. Do not silently skip or auto-correct — invalid transitions are almost always user typos and a clear error is the cheapest recovery.
|
|
72
|
+
|
|
73
|
+
### 4. Delegate the transition to `/wr-itil:manage-problem <NNN> <status>`
|
|
74
|
+
|
|
75
|
+
Invoke `/wr-itil:manage-problem` via the Skill tool with the `<NNN> <status>` argument shape. The delegated skill runs its Step 7 transition block, which owns:
|
|
76
|
+
|
|
77
|
+
- **Pre-flight checks** — root cause documented, investigation tasks checked off, reproduction test referenced, workaround documented, effort re-rated (P047). Any missing check halts the transition with a specific error.
|
|
78
|
+
- **P063 external-root-cause detection** — fires on Open → Known Error (and on the `upstream-blocked` park path). If a strict-token hit appears in the Root Cause Analysis section, the prompt routes the user to `/wr-itil:report-upstream` or defers with a stable marker. The AFK fallback (per ADR-013 Rule 6) appends the deferred-report marker automatically.
|
|
79
|
+
- **Staging trap handling (P057)** — after `git mv` renames the file, the Edit tool writes the Status field and (for the `verifying` destination) the `## Fix Released` section. The re-stage (`git add <new>`) is explicit — without it the content edit leaks into the next commit and the audit trail breaks.
|
|
80
|
+
- **README.md refresh (P062)** — regenerates `docs/problems/README.md` in-place on every transition so the dev-work table, Verification Queue, and Parked section never lag the on-disk ticket inventory. The refresh joins the same commit as the rename + content edit.
|
|
81
|
+
- **Commit per ADR-014** — governance skills commit their own work. Transition commits use the conventions named in the delegated skill's Step 11 block.
|
|
82
|
+
|
|
83
|
+
**Why delegate rather than re-implement:** the Step 7 block is a policy-governed, multi-concern flow (pre-flight + P063 + P057 + P062 + ADR-014 commit). Re-hosting it on a sibling skill would fork the ownership contract and compound maintenance cost. The split skill (this file) owns the *selection* of ticket + destination; `/wr-itil:manage-problem` owns the *execution*.
|
|
84
|
+
|
|
85
|
+
### 5. AFK / non-interactive branch (ADR-013 Rule 6)
|
|
86
|
+
|
|
87
|
+
When this skill is invoked inside an AFK orchestrator (detect via `/wr-itil:work-problems` markers in the invoking prompt — phrases like "AFK", "work-problems", "batch-work", "ALL_DONE"), do NOT emit `AskUserQuestion`. The orchestrator has already selected the transition (commonly Known Error → Verification Pending as part of a release commit) and this skill runs the execution only. The P063 external-root-cause detection's AFK fallback is owned by the delegated `/wr-itil:manage-problem` Step 7 block; this skill inherits that behaviour without re-implementing it.
|
|
88
|
+
|
|
89
|
+
Interactive mode (no orchestrator markers): the skill proceeds through Steps 1–4 directly. If any pre-flight check fails inside the delegated skill, the delegation returns that error and this skill surfaces it verbatim.
|
|
90
|
+
|
|
91
|
+
### 6. Report the outcome
|
|
92
|
+
|
|
93
|
+
After the delegated `/wr-itil:manage-problem <NNN> <status>` completes:
|
|
94
|
+
|
|
95
|
+
1. Report: ticket ID, previous Status, new Status, new filename, commit SHA.
|
|
96
|
+
2. If the destination was `verifying`, name the `## Fix Released` section's release marker in the output so the user can correlate with the shipped version.
|
|
97
|
+
3. **Do NOT re-commit or re-refresh** — the delegated skill already committed the change per ADR-014 and refreshed the README per P062. Re-emitting either would break the single-commit audit trail.
|
|
98
|
+
|
|
99
|
+
## Ownership boundary
|
|
100
|
+
|
|
101
|
+
`transition-problem` owns:
|
|
102
|
+
- Argument parsing (`<NNN> <status>`).
|
|
103
|
+
- Ticket-file discovery via `ls docs/problems/<NNN>-*.md`.
|
|
104
|
+
- Destination-reachability validation (Open → Known Error → Verification Pending → Closed, one step at a time).
|
|
105
|
+
- Delegating one transition execution to `/wr-itil:manage-problem <NNN> <status>`.
|
|
106
|
+
|
|
107
|
+
`transition-problem` does NOT:
|
|
108
|
+
- Run the Step 7 transition block inline — delegates to `/wr-itil:manage-problem`.
|
|
109
|
+
- Fire the P063 external-root-cause detection prompt directly — delegated skill owns it.
|
|
110
|
+
- Refresh `docs/problems/README.md` directly — delegated skill owns the refresh per P062.
|
|
111
|
+
- Commit — delegated skill commits per ADR-014.
|
|
112
|
+
- Park tickets — the `.parked.md` suffix has its own path on `/wr-itil:manage-problem` (P063 AFK fallback fires there too).
|
|
113
|
+
|
|
114
|
+
## Related
|
|
115
|
+
|
|
116
|
+
- **P071** (`docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md`) — originating ticket. This skill is phase 4 of the P071 phased-landing plan (list-problems was phase 1; review-problems was phase 2; work-problem was phase 3).
|
|
117
|
+
- **ADR-010 amended** (`docs/decisions/010-rename-wr-problem-to-wr-itil.proposed.md` — Skill Granularity section) — canonical skill-split naming + forwarder contract + `deprecated-arguments: true` frontmatter flag.
|
|
118
|
+
- **ADR-013** (`docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md`) — Rule 1 for interactive prompts; Rule 6 for the AFK non-interactive branch.
|
|
119
|
+
- **ADR-014** — governance skills commit their own work. The delegated `/wr-itil:manage-problem <NNN> <status>` owns the per-transition commit; this skill does not re-commit.
|
|
120
|
+
- **ADR-022** — `.verifying.md` suffix on release; Verification Pending is a first-class status distinct from Known Error. Known Error → Verification Pending is the most common transition this skill forwards.
|
|
121
|
+
- **ADR-032** — governance skill invocation patterns. `/wr-itil:work-problems` may delegate transition iterations to this skill during AFK release orchestration.
|
|
122
|
+
- **ADR-037** (`docs/decisions/037-skill-testing-strategy.proposed.md`) — contract-assertion bats pattern applied to this skill.
|
|
123
|
+
- **P057** — `git mv` + Edit staging trap rationale; the delegated Step 7 block implements the re-stage. Named here as a transitive contract so callers can reason about the dependency.
|
|
124
|
+
- **P062** — `/wr-itil:review-problems` is the canonical README.md cache writer, but Step 7 transitions also refresh README.md in-place per P062's mechanism. Named here as a transitive contract.
|
|
125
|
+
- **P063** — external-root-cause detection at Open → Known Error and at the `upstream-blocked` park path. The delegated Step 7 block owns the prompt; this skill inherits the AFK fallback without re-implementing.
|
|
126
|
+
- **JTBD-001** (`docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md`) — discoverable surface via `/wr-itil:` autocomplete. Users type `/wr-itil:transition-problem 042 known-error` rather than remembering the `manage-problem <NNN> known-error` subcommand.
|
|
127
|
+
- **JTBD-101** (`docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md`) — one skill per distinct user intent.
|
|
128
|
+
- `packages/itil/skills/manage-problem/SKILL.md` — hosts the thin-router forwarder for the deprecated `manage-problem <NNN> known-error` form; also the delegated execution target for each transition.
|
|
129
|
+
- `packages/itil/skills/review-problems/SKILL.md` — sibling refresh skill; this skill's transitions trigger the same README.md regeneration mechanism P062 codifies.
|
|
130
|
+
- `packages/itil/skills/list-problems/SKILL.md` — sibling read-only display skill; same cache contract.
|
|
131
|
+
- `packages/itil/skills/work-problem/SKILL.md` — sibling selection skill; delegates per-ticket execution (including transitions) through `/wr-itil:manage-problem`.
|
|
132
|
+
|
|
133
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env bats
|
|
2
|
+
# Contract assertions for /wr-itil:transition-problem (P071 split slice 4).
|
|
3
|
+
#
|
|
4
|
+
# This skill hosts the "advance a ticket's lifecycle" user intent
|
|
5
|
+
# previously hidden behind /wr-itil:manage-problem <NNN> known-error
|
|
6
|
+
# (and the sibling <NNN> close form). Transition renames the ticket
|
|
7
|
+
# file, updates the Status field, and refreshes docs/problems/README.md
|
|
8
|
+
# in the same commit per ADR-014 + ADR-022 + P062.
|
|
9
|
+
#
|
|
10
|
+
# Execution is delegated to /wr-itil:manage-problem <NNN> with the
|
|
11
|
+
# status argument — the Step 7 transition block on manage-problem owns
|
|
12
|
+
# the pre-flight checks, the P057 staging-trap handling, the external-
|
|
13
|
+
# root-cause detection (P063), the `## Fix Released` section writes,
|
|
14
|
+
# and the README.md refresh. This skill is a thin-router selection
|
|
15
|
+
# surface; execution stays on the authoritative workflow to avoid
|
|
16
|
+
# forking the transition logic.
|
|
17
|
+
#
|
|
18
|
+
# Structural assertion — Permitted Exception to the source-grep ban
|
|
19
|
+
# (ADR-005 / P011 / ADR-037 contract-assertion pattern).
|
|
20
|
+
#
|
|
21
|
+
# @problem P071
|
|
22
|
+
# @jtbd JTBD-001 (enforce governance without slowing down — discoverable surface)
|
|
23
|
+
# @jtbd JTBD-101 (extend the suite with clear patterns — one skill per distinct user intent)
|
|
24
|
+
#
|
|
25
|
+
# Cross-reference:
|
|
26
|
+
# P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
|
|
27
|
+
# ADR-010 amended (Skill Granularity section) — split naming + forwarder contract
|
|
28
|
+
# ADR-013 Rule 1 — structured user interaction (tie-break selection, if any)
|
|
29
|
+
# ADR-013 Rule 6 — AFK non-interactive fallback
|
|
30
|
+
# ADR-014 — governance skills commit their own work (delegated target owns commits)
|
|
31
|
+
# ADR-022 — .verifying.md suffix on release; Verification Pending distinct from Known Error
|
|
32
|
+
# ADR-037 — contract-assertion bats pattern
|
|
33
|
+
# P057 — git mv + Edit staging trap
|
|
34
|
+
# P062 — README.md refresh on every transition
|
|
35
|
+
# P063 — external-root-cause detection at Open → Known Error
|
|
36
|
+
|
|
37
|
+
setup() {
|
|
38
|
+
SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
39
|
+
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@test "SKILL.md exists and has frontmatter" {
|
|
43
|
+
[ -f "$SKILL_FILE" ]
|
|
44
|
+
run head -1 "$SKILL_FILE"
|
|
45
|
+
[ "$status" -eq 0 ]
|
|
46
|
+
[ "$output" = "---" ]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@test "SKILL.md frontmatter name is wr-itil:transition-problem (P071 + ADR-010 amended)" {
|
|
50
|
+
# Split naming convention per ADR-010 amendment: <verb>-<object>.
|
|
51
|
+
# The verb is "transition" (not "resolve", "advance", or
|
|
52
|
+
# "change-status") because the original subcommand form was
|
|
53
|
+
# `/wr-itil:manage-problem <NNN> known-error` — a status transition
|
|
54
|
+
# with a declarative destination. The P071 ticket's split proposal
|
|
55
|
+
# names this skill explicitly; the test locks the name in.
|
|
56
|
+
run grep -n "^name: wr-itil:transition-problem$" "$SKILL_FILE"
|
|
57
|
+
[ "$status" -eq 0 ]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@test "SKILL.md frontmatter description names the transition intent (P071)" {
|
|
61
|
+
# Description must name "transition" / "status" / one of the
|
|
62
|
+
# destination names (known-error / verifying / closed) so Claude Code
|
|
63
|
+
# autocomplete surfaces the user intent rather than a generic name.
|
|
64
|
+
run grep -inE "^description:.*(transition|status|lifecycle|advance)" "$SKILL_FILE"
|
|
65
|
+
[ "$status" -eq 0 ]
|
|
66
|
+
run grep -inE "^description:.*(known.error|verification|closed|verify)" "$SKILL_FILE"
|
|
67
|
+
[ "$status" -eq 0 ]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@test "SKILL.md frontmatter allowed-tools includes Skill (delegation to manage-problem)" {
|
|
71
|
+
# Step 3 delegates the per-ticket transition execution to
|
|
72
|
+
# /wr-itil:manage-problem <NNN> <status> via the Skill tool — the
|
|
73
|
+
# authoritative Step 7 block (pre-flight + P057 + P063 + P062) must
|
|
74
|
+
# remain on manage-problem to avoid forking the transition logic.
|
|
75
|
+
run grep -nE "^allowed-tools:.*Skill" "$SKILL_FILE"
|
|
76
|
+
[ "$status" -eq 0 ]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@test "SKILL.md frontmatter allowed-tools includes Bash (ticket-file discovery)" {
|
|
80
|
+
# Step 1 discovers the ticket file for a given ID by listing
|
|
81
|
+
# docs/problems/<NNN>-*.md. That's a Bash invocation; without the
|
|
82
|
+
# tool in allowed-tools, the discovery step cannot run.
|
|
83
|
+
run grep -nE "^allowed-tools:.*Bash" "$SKILL_FILE"
|
|
84
|
+
[ "$status" -eq 0 ]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@test "SKILL.md documents all three lifecycle transition destinations (ADR-022)" {
|
|
88
|
+
# The canonical lifecycle per ADR-022: Open → Known Error → Verification Pending → Closed.
|
|
89
|
+
# The skill must name each destination so users can pick the right
|
|
90
|
+
# transition. Missing any destination would leave a gap in the
|
|
91
|
+
# split coverage and force users back to the deprecated forwarder.
|
|
92
|
+
run grep -inE "known.error" "$SKILL_FILE"
|
|
93
|
+
[ "$status" -eq 0 ]
|
|
94
|
+
run grep -inE "verifying|verification.pending" "$SKILL_FILE"
|
|
95
|
+
[ "$status" -eq 0 ]
|
|
96
|
+
run grep -inE "\.closed\.md|closed" "$SKILL_FILE"
|
|
97
|
+
[ "$status" -eq 0 ]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@test "SKILL.md delegates transition execution to /wr-itil:manage-problem (anti-fork discipline)" {
|
|
101
|
+
# Per ADR-010 thin-router: the split skill owns intent selection,
|
|
102
|
+
# NOT execution. The pre-flight / staging-trap / P063 external-root-
|
|
103
|
+
# cause / README refresh stack stays on /wr-itil:manage-problem
|
|
104
|
+
# Step 7. If this skill re-implements the transition inline, the
|
|
105
|
+
# deprecation window hardens into a permanent fork.
|
|
106
|
+
run grep -inE "/wr-itil:manage-problem" "$SKILL_FILE"
|
|
107
|
+
[ "$status" -eq 0 ]
|
|
108
|
+
run grep -inE "delegate.*manage-problem|Skill tool.*manage-problem|manage-problem.*Skill tool" "$SKILL_FILE"
|
|
109
|
+
[ "$status" -eq 0 ]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@test "SKILL.md cites the P057 staging-trap rule (transitive contract)" {
|
|
113
|
+
# The delegated Step 7 block on manage-problem implements the
|
|
114
|
+
# staging-trap rule (re-stage after git mv + Edit). This skill must
|
|
115
|
+
# reference P057 so the transitive-contract dependency is legible —
|
|
116
|
+
# if the manage-problem Step 7 rule changes, this skill's delegation
|
|
117
|
+
# contract changes with it.
|
|
118
|
+
run grep -inE "P057|staging.trap|re-stage" "$SKILL_FILE"
|
|
119
|
+
[ "$status" -eq 0 ]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@test "SKILL.md cites the P062 README.md refresh rule (transitive contract)" {
|
|
123
|
+
# The delegated Step 7 block refreshes docs/problems/README.md on
|
|
124
|
+
# every transition. This skill must reference P062 so the
|
|
125
|
+
# downstream-refresh expectation is legible to callers (and so the
|
|
126
|
+
# skill does not mistakenly skip the refresh on the assumption that
|
|
127
|
+
# "the README is someone else's job").
|
|
128
|
+
run grep -inE "P062|README\.md.*refresh|refresh.*README\.md" "$SKILL_FILE"
|
|
129
|
+
[ "$status" -eq 0 ]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
@test "SKILL.md cites ADR-022 (Verification Pending is a first-class status)" {
|
|
133
|
+
# Known Error → Verification Pending is the transition most users
|
|
134
|
+
# will type this skill for (it fires on every released fix). The
|
|
135
|
+
# skill must cite ADR-022 so the semantic distinction — "Verification
|
|
136
|
+
# Pending means fix SHIPPED, not fix-path-clear" — stays legible.
|
|
137
|
+
run grep -inE "ADR-022" "$SKILL_FILE"
|
|
138
|
+
[ "$status" -eq 0 ]
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@test "SKILL.md documents the AFK non-interactive branch (ADR-013 Rule 6)" {
|
|
142
|
+
# When /wr-itil:work-problems invokes this skill inside an AFK
|
|
143
|
+
# subagent iteration, AskUserQuestion is unavailable — the skill
|
|
144
|
+
# must degrade gracefully. Common case: Known Error → Verification
|
|
145
|
+
# Pending fires automatically in the release-commit orchestration.
|
|
146
|
+
run grep -inE "AFK|non-interactive|ADR-013 Rule 6|Rule 6" "$SKILL_FILE"
|
|
147
|
+
[ "$status" -eq 0 ]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@test "SKILL.md does not carry a deprecated-arguments frontmatter flag (clean-split skill)" {
|
|
151
|
+
# Architect advisory: transition-problem is a clean-split skill. The
|
|
152
|
+
# deprecated-arguments flag is only valid on host skills with
|
|
153
|
+
# forwarder routes — transition-problem is a forwarder TARGET, not
|
|
154
|
+
# a host. The status argument (known-error / verifying / close) is
|
|
155
|
+
# a *data parameter*, not a word-subcommand, per the P071 split rule.
|
|
156
|
+
run grep -E "^deprecated-arguments:" "$SKILL_FILE"
|
|
157
|
+
[ "$status" -ne 0 ]
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@test "SKILL.md cites P071 and ADR-010 amended (traceability per ADR-037)" {
|
|
161
|
+
# ADR-037 traceability: the skill spec cites the problem it closes
|
|
162
|
+
# and the ADR that authorises the split.
|
|
163
|
+
run grep -inE "P071|ADR-010" "$SKILL_FILE"
|
|
164
|
+
[ "$status" -eq 0 ]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@test "SKILL.md documents the ticket-ID data-parameter shape (not a word-subcommand)" {
|
|
168
|
+
# The ticket ID (<NNN>) is a data parameter per P071's split rule.
|
|
169
|
+
# The status destination (known-error / verifying / close) is ALSO
|
|
170
|
+
# a data parameter — the user supplies it alongside the ID. This is
|
|
171
|
+
# the same shape as /wr-itil:report-upstream <NNN>: data parameters
|
|
172
|
+
# are fine, word-subcommands routing to distinct user intents are not.
|
|
173
|
+
run grep -inE "<NNN>|ticket.{0,5}ID|ID.*argument|data parameter" "$SKILL_FILE"
|
|
174
|
+
[ "$status" -eq 0 ]
|
|
175
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wr-itil:work-problem
|
|
3
|
+
description: Pick the highest-WSJF open or known-error problem ticket and work it — investigate, implement, commit, and release per the standard manage-problem workflow. Interactive singular variant; distinct from /wr-itil:work-problems (plural AFK orchestrator). Use this when the user asks to "work the next problem", "work the top of the queue", or "grind through one ticket".
|
|
4
|
+
allowed-tools: Read, Write, Edit, Bash, Glob, Grep, AskUserQuestion, Skill, Agent
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Work Problem — Pick-and-Run
|
|
8
|
+
|
|
9
|
+
Pick the highest-WSJF ticket from the current backlog and work it end-to-end. This is the **singular, interactive** entry point — one ticket per invocation, driven by an `AskUserQuestion` selection when the WSJF ranking is tied.
|
|
10
|
+
|
|
11
|
+
This skill is the P071 phased-landing split of `/wr-itil:manage-problem work` per ADR-010 amended Skill Granularity rule: one skill per distinct user intent. The original `/wr-itil:manage-problem work` subcommand route remains as a thin-router forwarder during the deprecation window but is scheduled for removal in `@windyroad/itil`'s next major version.
|
|
12
|
+
|
|
13
|
+
## Name distinction (work-problem vs work-problems)
|
|
14
|
+
|
|
15
|
+
- **`/wr-itil:work-problem`** (singular, this skill) — one ticket per invocation. Interactive `AskUserQuestion` selection. Intended for a user who wants to dispatch the next-highest ticket and then stop.
|
|
16
|
+
- **`/wr-itil:work-problems`** (plural, AFK orchestrator) — loops through the backlog by WSJF, delegating each iteration to this skill (via the Agent tool, per ADR-032 + P077). Intended for AFK batch runs; non-interactive selection; stops only when nothing actionable remains.
|
|
17
|
+
|
|
18
|
+
Both names coexist intentionally per P071's out-of-scope note on the naming coexistence. The plural orchestrator uses this skill as its per-iteration unit.
|
|
19
|
+
|
|
20
|
+
## Scope
|
|
21
|
+
|
|
22
|
+
**In scope:**
|
|
23
|
+
- Read `docs/problems/README.md` when fresh; otherwise delegate the refresh to `/wr-itil:review-problems` first (never re-implement the re-scoring logic locally — same anti-fork discipline as the list-problems cache path).
|
|
24
|
+
- Select the highest-WSJF ticket via `AskUserQuestion` (structured-interaction path per ADR-013 Rule 1). Present ties as peer options with per-option rationale.
|
|
25
|
+
- Delegate the actual work to `/wr-itil:manage-problem <NNN>` via the Skill tool so the investigation / known-error transition / fix / closure flow stays hosted on a single authoritative workflow (ADR-010 thin-router discipline applied to the work path).
|
|
26
|
+
- Scope-expansion prompt (ADR-013 Rule 1) when the selected ticket's effort grows during work — same three-option structure as `/wr-itil:manage-problem`'s Working a Problem section.
|
|
27
|
+
|
|
28
|
+
**Out of scope:**
|
|
29
|
+
- Batch looping over multiple tickets — that's `/wr-itil:work-problems` (plural). This skill runs exactly one ticket per invocation.
|
|
30
|
+
- Backlog re-ranking / Verification Queue prompt / README.md refresh — that's `/wr-itil:review-problems`. This skill reads the ranking; it does not rewrite it.
|
|
31
|
+
- Ticket creation — that's `/wr-itil:manage-problem` (no-args form).
|
|
32
|
+
- Status transitions other than those driven by the delegated `/wr-itil:manage-problem <NNN>` flow.
|
|
33
|
+
|
|
34
|
+
## Steps
|
|
35
|
+
|
|
36
|
+
### 1. Ensure the ranking is fresh
|
|
37
|
+
|
|
38
|
+
Check the `docs/problems/README.md` cache with the same git-history-based freshness test as `/wr-itil:list-problems` and `/wr-itil:review-problems` (per P031 — filesystem mtime is unreliable in worktrees and fresh checkouts, so git history is the authoritative staleness signal):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
readme_commit=$(git log -1 --format=%H -- docs/problems/README.md 2>/dev/null)
|
|
42
|
+
if [ -z "$readme_commit" ] || \
|
|
43
|
+
git log --oneline "${readme_commit}..HEAD" -- 'docs/problems/*.md' ':!docs/problems/README.md' 2>/dev/null | grep -q .; then
|
|
44
|
+
echo "stale"
|
|
45
|
+
fi
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- **Cache fresh** (no output): read `docs/problems/README.md` and use the cached WSJF Rankings table for Step 2.
|
|
49
|
+
- **Cache stale** (prints "stale") or `README.md` missing: **delegate to `/wr-itil:review-problems`** via the Skill tool to refresh the ranking before proceeding. Do NOT re-implement the re-scoring logic here — that would fork the review path and break P062's canonical-cache-writer contract. The review skill's Step 4 verification prompt runs on this refresh path (P048 Candidate 1: Verification Queue prompts always fire so pending verifications don't accumulate off-ledger).
|
|
50
|
+
|
|
51
|
+
### 2. Select the ticket
|
|
52
|
+
|
|
53
|
+
Read the WSJF Rankings table from the now-fresh `docs/problems/README.md`. Parse the top rows to find the highest-WSJF ticket(s).
|
|
54
|
+
|
|
55
|
+
**Selection via `AskUserQuestion`** (ADR-013 Rule 1 structured-interaction path):
|
|
56
|
+
|
|
57
|
+
- **Single top-WSJF ticket** (strictly higher than all others): present as the recommended option:
|
|
58
|
+
- Option 1: `Work P<NNN>: <title> (Recommended)` — description shows WSJF score, Severity, and Status.
|
|
59
|
+
- Option 2: `Pick a different problem` — user names a specific ID in the free-form response.
|
|
60
|
+
- **Tied top-WSJF tickets** (two or more tied for the highest WSJF): present each tied ticket as a peer option. Per-option description carries a one-line rationale naming the Status / Effort / concrete next action so the user can pick with context:
|
|
61
|
+
- One option per tied ticket: `Work P<NNN>: <title>` — description: `WSJF <score> · <status> · <effort> · <one-line rationale>`.
|
|
62
|
+
- Final option: `Pick a different problem`.
|
|
63
|
+
- Use `header: "Next problem"` and `multiSelect: false`.
|
|
64
|
+
|
|
65
|
+
**Never present the selection as prose "(a)/(b)/(c)" or "which would you like?"** — always use `AskUserQuestion` so the decision is structured and auditable. This is the same discipline `/wr-itil:manage-problem` Step 9c carries; the split lifts it verbatim.
|
|
66
|
+
|
|
67
|
+
**AFK / non-interactive branch (ADR-013 Rule 6)**: when this skill is invoked inside an AFK orchestrator (detect via `/wr-itil:work-problems` markers in the invoking prompt — phrases like "AFK", "work-problems", "batch-work", "ALL_DONE"), apply the within-day tiebreak per `/wr-itil:work-problems` Step 1c: Known Error > Open; smaller Effort; older reported date; ticket number ascending. Do NOT emit `AskUserQuestion` in AFK mode — the orchestrator has already selected the iteration and this skill runs the execution only.
|
|
68
|
+
|
|
69
|
+
### 3. Delegate the work to `/wr-itil:manage-problem <NNN>`
|
|
70
|
+
|
|
71
|
+
Invoke `/wr-itil:manage-problem <NNN>` via the Skill tool with the selected ticket's ID as the argument. The delegated skill runs the full Working a Problem flow appropriate to the ticket's status:
|
|
72
|
+
|
|
73
|
+
- **Open ticket**: investigate root cause; document findings; create reproduction test; identify workaround; auto-transition to Known Error when root cause + workaround are documented; if the fix is small, proceed straight into implementation.
|
|
74
|
+
- **Known Error**: read the root cause analysis; implement the fix following the project's standard workflow (plan if needed, architect review, tests, changeset); include the Known Error → Verification Pending `git mv` in the fix commit per ADR-022.
|
|
75
|
+
|
|
76
|
+
**Why delegate rather than re-implement:** the full investigation / transition / fix / release pipeline is a long-lived, policy-governed flow that must stay on a single authoritative workflow. Re-hosting it on a sibling skill would fork the ownership contract and compound maintenance cost. The split skill (this file) owns the *selection* of the next ticket; `/wr-itil:manage-problem <NNN>` owns the *execution*.
|
|
77
|
+
|
|
78
|
+
### 4. Scope-expansion check (ADR-013 Rule 1)
|
|
79
|
+
|
|
80
|
+
If the delegated `/wr-itil:manage-problem <NNN>` reports that the ticket's effort expanded during investigation or architect review (e.g. S → L, or L → XL), fire the standard scope-change `AskUserQuestion` prompt:
|
|
81
|
+
|
|
82
|
+
- Option 1: `Continue with expanded scope` — keep working this ticket at its new size.
|
|
83
|
+
- Option 2: `Update problem and re-rank` — save findings to the problem file, re-score WSJF, and re-run the work selection to let the user pick from the updated queue.
|
|
84
|
+
- Option 3: `Pick a different problem` — park this one and work something else.
|
|
85
|
+
|
|
86
|
+
Use `header: "Scope change"` and `multiSelect: false`. This is the same structure `/wr-itil:manage-problem`'s Working a Problem section documents; the split lifts it without modification.
|
|
87
|
+
|
|
88
|
+
**AFK / non-interactive branch**: same ADR-013 Rule 6 fallback as `/wr-itil:work-problems` — save findings + the new Effort/WSJF lines to the ticket file and skip to the next iteration. The orchestrator owns the re-selection loop.
|
|
89
|
+
|
|
90
|
+
### 5. Post-work housekeeping
|
|
91
|
+
|
|
92
|
+
After the delegated `/wr-itil:manage-problem <NNN>` completes:
|
|
93
|
+
|
|
94
|
+
1. If the ticket status changed (Open → Known Error, Known Error → Verification Pending), the delegated skill already committed the change per ADR-014 + ADR-022 and updated `docs/problems/README.md` per P062. This skill does NOT re-commit or re-refresh; it reports what happened.
|
|
95
|
+
2. Report the outcome: ticket ID, action taken (investigated / transitioned / fix-released), commit SHA(s), and next-recommended action (typically "run `/wr-itil:work-problem` again for the next ticket" or "stop — all actionable tickets worked").
|
|
96
|
+
3. **Do NOT loop automatically.** This is the singular skill. If the user wants to continue, they invoke `/wr-itil:work-problem` again, or switch to `/wr-itil:work-problems` (plural) for the AFK orchestrator loop.
|
|
97
|
+
|
|
98
|
+
## Ownership boundary
|
|
99
|
+
|
|
100
|
+
`work-problem` (singular) owns:
|
|
101
|
+
- Reading the WSJF Rankings from `docs/problems/README.md`.
|
|
102
|
+
- Firing the `AskUserQuestion` selection prompt (interactive mode).
|
|
103
|
+
- Delegating one execution iteration to `/wr-itil:manage-problem <NNN>`.
|
|
104
|
+
- Firing the scope-expansion `AskUserQuestion` on effort drift.
|
|
105
|
+
|
|
106
|
+
`work-problem` does NOT:
|
|
107
|
+
- Refresh the README.md cache directly — defers to `/wr-itil:review-problems`.
|
|
108
|
+
- Loop over multiple tickets — that's `/wr-itil:work-problems` (plural).
|
|
109
|
+
- Commit the ranking refresh or the per-ticket work — delegated skills commit per ADR-014.
|
|
110
|
+
|
|
111
|
+
## Related
|
|
112
|
+
|
|
113
|
+
- **P071** (`docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md`) — originating ticket. This skill is phase 3 of the P071 phased-landing plan (list-problems was phase 1; review-problems was phase 2).
|
|
114
|
+
- **ADR-010 amended** (`docs/decisions/010-rename-wr-problem-to-wr-itil.proposed.md` — Skill Granularity section) — canonical skill-split naming + forwarder contract + `deprecated-arguments: true` frontmatter flag.
|
|
115
|
+
- **ADR-013** (`docs/decisions/013-structured-user-interaction-for-governance-decisions.proposed.md`) — Rule 1 for the interactive `AskUserQuestion` selection; Rule 6 for the AFK-orchestrator non-interactive branch.
|
|
116
|
+
- **ADR-014** — governance skills commit their own work. The delegated `/wr-itil:manage-problem <NNN>` owns the per-ticket commit; this skill does not re-commit.
|
|
117
|
+
- **ADR-018** — release cadence. AFK orchestrator owns release cadence; this skill does NOT auto-release.
|
|
118
|
+
- **ADR-032** — governance skill invocation patterns. `/wr-itil:work-problems` delegates iterations via the Agent tool; this singular skill is the canonical execution unit.
|
|
119
|
+
- **ADR-037** (`docs/decisions/037-skill-testing-strategy.proposed.md`) — contract-assertion bats pattern applied to this skill.
|
|
120
|
+
- **P031** — git-history freshness check rationale (mtime unreliable in worktrees). Applies to the README cache this skill reads.
|
|
121
|
+
- **P062** — `/wr-itil:review-problems` is the canonical README.md cache writer. This skill defers to it for refreshes.
|
|
122
|
+
- **P077** — `/wr-itil:work-problems` Step 5 delegates iterations via the Agent tool. The delegated subagent invokes this skill's execution unit per iteration.
|
|
123
|
+
- **JTBD-001** (`docs/jtbd/solo-developer/JTBD-001-enforce-governance.proposed.md`) — discoverable surface via `/wr-itil:` autocomplete. Users type `/wr-itil:work-problem` rather than remembering the `manage-problem work` subcommand.
|
|
124
|
+
- **JTBD-101** (`docs/jtbd/plugin-developer/JTBD-101-extend-suite.proposed.md`) — one skill per distinct user intent.
|
|
125
|
+
- `packages/itil/skills/manage-problem/SKILL.md` — hosts the thin-router forwarder for the deprecated `manage-problem work` form; also the delegated execution target for each ticket.
|
|
126
|
+
- `packages/itil/skills/review-problems/SKILL.md` — sibling refresh skill; this skill defers to it when the cache is stale.
|
|
127
|
+
- `packages/itil/skills/list-problems/SKILL.md` — sibling read-only display skill; same cache read contract.
|
|
128
|
+
- `packages/itil/skills/work-problems/SKILL.md` — plural AFK orchestrator; uses this skill as its per-iteration execution unit.
|
|
129
|
+
|
|
130
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,206 @@
|
|
|
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
|
+
# @problem P071
|
|
16
|
+
# @jtbd JTBD-001 (enforce governance without slowing down — discoverable surface)
|
|
17
|
+
# @jtbd JTBD-101 (extend the suite with clear patterns — one skill per distinct user intent)
|
|
18
|
+
#
|
|
19
|
+
# Cross-reference:
|
|
20
|
+
# P071: docs/problems/071-argument-based-skill-subcommands-are-not-discoverable.open.md
|
|
21
|
+
# ADR-010 amended (Skill Granularity section) — split naming + forwarder contract
|
|
22
|
+
# ADR-013 Rule 1 — structured user interaction (AskUserQuestion selection prompt)
|
|
23
|
+
# ADR-013 Rule 6 — AFK non-interactive fallback
|
|
24
|
+
# ADR-014 — governance skills commit their own work (delegated target owns commits)
|
|
25
|
+
# ADR-032 — governance skill invocation patterns (plural orchestrator delegates here)
|
|
26
|
+
# ADR-037 — contract-assertion bats pattern
|
|
27
|
+
|
|
28
|
+
setup() {
|
|
29
|
+
SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
|
|
30
|
+
SKILL_FILE="${SKILL_DIR}/SKILL.md"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@test "SKILL.md exists and has frontmatter" {
|
|
34
|
+
[ -f "$SKILL_FILE" ]
|
|
35
|
+
run head -1 "$SKILL_FILE"
|
|
36
|
+
[ "$status" -eq 0 ]
|
|
37
|
+
[ "$output" = "---" ]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@test "SKILL.md frontmatter name is wr-itil:work-problem (singular, P071 + ADR-010 amended)" {
|
|
41
|
+
# Split naming convention per ADR-010 amendment: <verb>-<object>.
|
|
42
|
+
# CRITICAL: singular "work-problem", NOT plural "work-problems" — the
|
|
43
|
+
# plural name is reserved for the AFK orchestrator that already exists.
|
|
44
|
+
# Name coexistence is a P071 acknowledged trade-off.
|
|
45
|
+
run grep -n "^name: wr-itil:work-problem$" "$SKILL_FILE"
|
|
46
|
+
[ "$status" -eq 0 ]
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@test "SKILL.md frontmatter name is NOT wr-itil:work-problems (regression guard for name collision)" {
|
|
50
|
+
# Guard against the easy slip of renaming this skill to match the
|
|
51
|
+
# plural orchestrator. If the name drifts to plural, `/wr-itil:`
|
|
52
|
+
# autocomplete shows two plural-looking skills side by side and users
|
|
53
|
+
# cannot tell which is interactive vs batch.
|
|
54
|
+
run grep -n "^name: wr-itil:work-problems$" "$SKILL_FILE"
|
|
55
|
+
[ "$status" -ne 0 ]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@test "SKILL.md frontmatter description names the pick-and-run intent (P071)" {
|
|
59
|
+
# Description must name "pick" / "work" / "highest-WSJF" so Claude
|
|
60
|
+
# Code autocomplete surfaces the user intent rather than a generic
|
|
61
|
+
# name. Also must mention "singular" or distinguish from the plural
|
|
62
|
+
# orchestrator so users pick the right one.
|
|
63
|
+
run grep -inE "^description:.*(pick|highest.wsjf|work.*problem)" "$SKILL_FILE"
|
|
64
|
+
[ "$status" -eq 0 ]
|
|
65
|
+
run grep -inE "^description:.*(singular|one ticket|distinct from.*work-problems)" "$SKILL_FILE"
|
|
66
|
+
[ "$status" -eq 0 ]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@test "SKILL.md frontmatter allowed-tools includes AskUserQuestion (selection prompt)" {
|
|
70
|
+
# Step 2 fires AskUserQuestion for the selection in interactive mode
|
|
71
|
+
# (ADR-013 Rule 1). Without the tool the structured-interaction
|
|
72
|
+
# contract cannot hold.
|
|
73
|
+
run grep -nE "^allowed-tools:.*AskUserQuestion" "$SKILL_FILE"
|
|
74
|
+
[ "$status" -eq 0 ]
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@test "SKILL.md frontmatter allowed-tools includes Skill (delegation to manage-problem + review-problems)" {
|
|
78
|
+
# Step 1 delegates the cache refresh to /wr-itil:review-problems when
|
|
79
|
+
# stale; Step 3 delegates the per-ticket execution to
|
|
80
|
+
# /wr-itil:manage-problem <NNN>. Both use the Skill tool per ADR-010's
|
|
81
|
+
# thin-router discipline.
|
|
82
|
+
run grep -nE "^allowed-tools:.*Skill" "$SKILL_FILE"
|
|
83
|
+
[ "$status" -eq 0 ]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@test "SKILL.md documents the singular-vs-plural naming distinction (P071 coexistence)" {
|
|
87
|
+
# The most common user confusion will be work-problem vs
|
|
88
|
+
# work-problems. The SKILL.md must name the distinction explicitly
|
|
89
|
+
# so `/wr-itil:` autocomplete readers can tell them apart. Without
|
|
90
|
+
# this, users will pick the wrong one and either run a single ticket
|
|
91
|
+
# when they wanted the AFK loop or vice-versa.
|
|
92
|
+
run grep -inE "work-problems.*plural|plural.*work-problems|AFK orchestrator" "$SKILL_FILE"
|
|
93
|
+
[ "$status" -eq 0 ]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@test "SKILL.md delegates execution to /wr-itil:manage-problem (anti-fork discipline)" {
|
|
97
|
+
# Per ADR-010 thin-router: the split skill owns selection, NOT
|
|
98
|
+
# execution. The per-ticket investigate/transition/fix/release flow
|
|
99
|
+
# stays on /wr-itil:manage-problem <NNN>. If this skill re-implements
|
|
100
|
+
# the execution inline, the deprecation window hardens into a
|
|
101
|
+
# permanent fork.
|
|
102
|
+
run grep -inE "/wr-itil:manage-problem" "$SKILL_FILE"
|
|
103
|
+
[ "$status" -eq 0 ]
|
|
104
|
+
run grep -inE "delegate.*manage-problem|Skill tool.*manage-problem|manage-problem.*Skill tool" "$SKILL_FILE"
|
|
105
|
+
[ "$status" -eq 0 ]
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@test "SKILL.md defers README.md cache refresh to /wr-itil:review-problems (P062 ownership)" {
|
|
109
|
+
# P062 makes /wr-itil:review-problems the canonical README.md cache
|
|
110
|
+
# writer. This skill reads the cache but must NOT rewrite it —
|
|
111
|
+
# re-implementing the refresh here would break the one-canonical-
|
|
112
|
+
# writer invariant.
|
|
113
|
+
run grep -inE "/wr-itil:review-problems" "$SKILL_FILE"
|
|
114
|
+
[ "$status" -eq 0 ]
|
|
115
|
+
run grep -inE "(delegate|defer|refresh).*review-problems|review-problems.*(refresh|delegate|defer)" "$SKILL_FILE"
|
|
116
|
+
[ "$status" -eq 0 ]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@test "SKILL.md reads README.md cache via the git-history freshness test (P031)" {
|
|
120
|
+
# Same freshness check as list-problems and review-problems — mtime
|
|
121
|
+
# is unreliable in worktrees per P031. Drift here means false
|
|
122
|
+
# cache-hit (serving a stale ranking) or false cache-miss (spamming
|
|
123
|
+
# review refreshes).
|
|
124
|
+
run grep -inE "docs/problems/README\.md" "$SKILL_FILE"
|
|
125
|
+
[ "$status" -eq 0 ]
|
|
126
|
+
run grep -inE "git log.*--format.*README\.md|readme_commit" "$SKILL_FILE"
|
|
127
|
+
[ "$status" -eq 0 ]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@test "SKILL.md fires the AskUserQuestion selection prompt (ADR-013 Rule 1)" {
|
|
131
|
+
# Step 2 is the structured-interaction path: single top-WSJF ticket
|
|
132
|
+
# shown as Recommended, or tied tickets shown as peer options. Never
|
|
133
|
+
# prose "(a)/(b)/(c)".
|
|
134
|
+
run grep -inE "AskUserQuestion" "$SKILL_FILE"
|
|
135
|
+
[ "$status" -eq 0 ]
|
|
136
|
+
run grep -inE "Next problem|Recommended|tied" "$SKILL_FILE"
|
|
137
|
+
[ "$status" -eq 0 ]
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@test "SKILL.md forbids prose selection fallback (P053 + ADR-013 Rule 1 regression guard)" {
|
|
141
|
+
# Prose "which would you like?" or "(a)/(b)/(c)" is the anti-pattern
|
|
142
|
+
# ADR-013 Rule 1 and P053 codify against. The SKILL.md must say
|
|
143
|
+
# "never" so the contract is legible at the spec level.
|
|
144
|
+
run grep -inE "never.*prose|never.*\(a\)/\(b\)" "$SKILL_FILE"
|
|
145
|
+
[ "$status" -eq 0 ]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@test "SKILL.md documents the AFK non-interactive branch (ADR-013 Rule 6)" {
|
|
149
|
+
# When /wr-itil:work-problems invokes this skill inside an AFK
|
|
150
|
+
# subagent iteration, AskUserQuestion is unavailable — the selection
|
|
151
|
+
# has already happened at the orchestrator level. The skill must
|
|
152
|
+
# degrade gracefully per Rule 6.
|
|
153
|
+
run grep -inE "AFK|non-interactive|ADR-013 Rule 6|Rule 6" "$SKILL_FILE"
|
|
154
|
+
[ "$status" -eq 0 ]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@test "SKILL.md documents the scope-expansion AskUserQuestion (3-option shape)" {
|
|
158
|
+
# Effort drift during investigation or architect review must fire the
|
|
159
|
+
# standard Continue / Re-rank / Pick-different three-option prompt,
|
|
160
|
+
# same as /wr-itil:manage-problem's Working a Problem section.
|
|
161
|
+
run grep -inE "Scope change|scope.expansion" "$SKILL_FILE"
|
|
162
|
+
[ "$status" -eq 0 ]
|
|
163
|
+
run grep -inE "Continue with expanded scope|Update problem and re-rank|Pick a different problem" "$SKILL_FILE"
|
|
164
|
+
[ "$status" -eq 0 ]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@test "SKILL.md runs exactly one ticket per invocation (singular contract)" {
|
|
168
|
+
# The whole point of the singular skill: one ticket, then stop. The
|
|
169
|
+
# SKILL.md must say "do not loop automatically" or equivalent so the
|
|
170
|
+
# contract is explicit. Looping is the plural orchestrator's job.
|
|
171
|
+
run grep -inE "do not loop automatically|one ticket per invocation|singular" "$SKILL_FILE"
|
|
172
|
+
[ "$status" -eq 0 ]
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@test "SKILL.md does not carry a deprecated-arguments frontmatter flag (clean-split skill)" {
|
|
176
|
+
# Architect advisory: work-problem is a clean-split skill with no
|
|
177
|
+
# argument-subcommands itself. ADR-010 amendment's
|
|
178
|
+
# `deprecated-arguments: true` flag is only valid on host skills with
|
|
179
|
+
# forwarder routes — work-problem is a forwarder TARGET, not a host.
|
|
180
|
+
run grep -E "^deprecated-arguments:" "$SKILL_FILE"
|
|
181
|
+
[ "$status" -ne 0 ]
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@test "SKILL.md does not use word-argument subcommand branching (P071 regression guard)" {
|
|
185
|
+
# The whole point of P071: Claude Code autocomplete does not surface
|
|
186
|
+
# arguments. A clean-split skill must not reintroduce word-arg
|
|
187
|
+
# subcommand routing.
|
|
188
|
+
run grep -inE "If arguments start with|If arguments contain" "$SKILL_FILE"
|
|
189
|
+
[ "$status" -ne 0 ]
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@test "SKILL.md cites P071 and ADR-010 amended (traceability per ADR-037)" {
|
|
193
|
+
# ADR-037 traceability: the skill spec cites the problem it closes
|
|
194
|
+
# and the ADR that authorises the split.
|
|
195
|
+
run grep -inE "P071|ADR-010" "$SKILL_FILE"
|
|
196
|
+
[ "$status" -eq 0 ]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
@test "SKILL.md cites ADR-032 + P077 (AFK orchestrator delegation target)" {
|
|
200
|
+
# /wr-itil:work-problems Step 5 delegates iterations via the Agent
|
|
201
|
+
# tool (P077). This skill is the execution unit those iterations
|
|
202
|
+
# invoke. The cross-reference documents the pair relationship so
|
|
203
|
+
# future drift to /wr-itil:work-problems doesn't orphan this skill.
|
|
204
|
+
run grep -inE "P077|ADR-032" "$SKILL_FILE"
|
|
205
|
+
[ "$status" -eq 0 ]
|
|
206
|
+
}
|