@windyroad/itil 0.43.0 → 0.44.0-preview.501

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.
@@ -497,5 +497,5 @@
497
497
  }
498
498
  },
499
499
  "name": "wr-itil",
500
- "version": "0.43.0"
500
+ "version": "0.44.0"
501
501
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.43.0",
3
+ "version": "0.44.0-preview.501",
4
4
  "description": "ITIL-aligned IT service management for Claude Code (problem, and future incident/change skills)",
5
5
  "bin": {
6
6
  "windyroad-itil": "./bin/install.mjs"
@@ -545,7 +545,14 @@ After writing the new `.open.md` file, regenerate `docs/problems/README.md` to i
545
545
  **Likely-verified cell shape (P186)**: the `Likely verified?` column carries an **evidence-first** cell — `yes — observed: <evidence>` / `no — not observed` / `no — observed regression`. The 14-day age-based heuristic (originally introduced by P048 Candidate 4) is superseded — age is preserved separately via the `Released` column; the `Likely verified?` column is reserved for session-observed evidence (Step 4 user confirmation, in-session test invocation outcome per ADR-026 grounding, or `run-retro` Step 4a close-on-evidence citation). <!-- LIKELY-VERIFIED-CELL-SHAPE: evidence-based per P186 --> Any future change to the cell shape MUST update this render block, the Step 7 P062 block, the Step 9c presentation block, the Step 9e template, AND `/wr-itil:review-problems` + `/wr-itil:transition-problem` + `/wr-itil:transition-problems` + `/wr-itil:reconcile-readme` + `/wr-itil:list-problems` — drift here re-opens P186.
546
546
 
547
547
  1. After `Write`-ing the new `.open.md` file (and, for multi-concern splits per step 4b, after all split files are written), regenerate `docs/problems/README.md` in-place reflecting the new filename set.
548
- 2. Update the "Last reviewed" line per the **Last-reviewed line discipline (P134)** subsection below name the new ticket as the most-recent fragment (e.g. `P<NNN> opened <one-line title>`); displaced prior fragments rotate to `docs/problems/README-history.md`.
548
+ 2. Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection further down this SKILL) so a single-pass agent reading this Step 5 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
549
+
550
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
551
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
552
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> opened — <one-line title>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
553
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 captures both files.
554
+
555
+ Canonical rationale anchor: § Last-reviewed line discipline (P134) subsection below. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
549
556
  3. `git add docs/problems/README.md` — the stage list at Step 11 must include it alongside the new `.open.md` file (Step 11's `git add -u` catch-all handles tracked-file modifications; the new README render lands via this path when README.md already exists in git, and via an explicit `git add docs/problems/README.md` when it is newly created). When line-3 truncation displaces prior content, also `git add docs/problems/README-history.md`.
550
557
 
551
558
  For the multi-concern split path (step 4b), the refresh fires **once** after all split tickets are written, not per-split — a single render captures the full new set in one pass.
@@ -602,7 +609,14 @@ If the edit touched only `## Root Cause Analysis`, `## Symptoms`, `## Workaround
602
609
  **Mechanism** (when the trigger fires):
603
610
 
604
611
  1. Regenerate `docs/problems/README.md` using the same render rules as Step 7's P062 block — render, not re-rank. Trust every other ticket's stored WSJF; consume only this ticket's updated WSJF from the post-edit file.
605
- 2. Update the "Last reviewed" line per the **Last-reviewed line discipline (P134)** subsection in Step 5 above name the re-rated ticket as the most-recent fragment (e.g. `P<NNN> re-rated <old-WSJF> <new-WSJF>`); displaced prior fragments rotate to `docs/problems/README-history.md`.
612
+ 2. Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection further up this SKILL) so a single-pass agent reading this Step 6 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331**. The mechanism MUST execute IN ORDER:
613
+
614
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md`.
615
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
616
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> re-rated — <old-WSJF> → <new-WSJF>`). Soft cap ≤ 1024 bytes; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
617
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 captures both files.
618
+
619
+ Canonical rationale anchor: § Last-reviewed line discipline (P134) subsection in Step 5 above. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
606
620
  3. `git add docs/problems/README.md` so the refresh rides the same commit as the ticket update per ADR-014. When line-3 truncation displaces prior content, also `git add docs/problems/README-history.md`.
607
621
 
608
622
  **Dependency ripple**: if this update changed the ticket's Effort, and the ticket is an upstream of other tickets (any ticket's `## Dependencies` → `**Blocked by**` list references this ID), the transitive-effort rule (P076) says dependents may need to re-rate too. The surgical render in this step does NOT re-walk the graph — that is Step 9b.1's job. If the dependency graph is known to be non-trivial, prefer `/wr-itil:review-problems` instead of a bare update; the review path handles the re-walk deterministically. The conditional refresh here is sufficient for the common case of a self-only re-rate.
@@ -717,7 +731,14 @@ The refresh uses the same rendering rules as Step 9e (dual-tolerant glob per RFC
717
731
 
718
732
  1. After renaming + Editing + `git add`-ing the transitioned ticket file (per the staging-trap rule above), regenerate `docs/problems/README.md` in-place reflecting the new filename set and the transitioned ticket's new Status.
719
733
  2. `git add docs/problems/README.md` — stage the refreshed README with the same commit as the transition.
720
- 3. Update the "Last reviewed" line per the **Last-reviewed line discipline (P134)** subsection in Step 5 above name the transition as the most-recent fragment (e.g. `P<NNN> <status> <one-line fix summary>`); displaced prior fragments rotate to `docs/problems/README-history.md`. When the rotation displaces prior content, the staged file set MUST include both `docs/problems/README.md` AND `docs/problems/README-history.md` per ADR-014 single-commit grain.
734
+ 3. Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to the § Last-reviewed line discipline subsection in Step 5 above) so a single-pass agent reading this Step 7 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
735
+
736
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
737
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
738
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> <status> — <one-line fix summary>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
739
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 single-commit grain captures both files.
740
+
741
+ Canonical rationale anchor: § Last-reviewed line discipline (P134) subsection in Step 5 above. The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
721
742
 
722
743
  **Scope**: fires for every Step 7 rename. Applies equally to:
723
744
  - Standalone transition commits (e.g. `docs(problems): P<NNN> known error — <summary>`).
@@ -131,7 +131,16 @@ git add docs/rfcs/RFC-<NNN>-<slug>.<new-status>.md
131
131
 
132
132
  #### README refresh on every transition (P062 mirror)
133
133
 
134
- After renaming + Editing + `git add`-ing the transitioned RFC file, regenerate `docs/rfcs/README.md` in-place reflecting the new filename set and the transitioned RFC's new Status. Stage the refreshed README with the same commit. The "Last reviewed" line on `docs/rfcs/README.md` follows the same P134 truncation discipline as `docs/problems/README.md`: single most-recent fragment on line 3; displaced fragments rotate to `docs/rfcs/README-history.md` (created on first rotation). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
134
+ After renaming + Editing + `git add`-ing the transitioned RFC file, regenerate `docs/rfcs/README.md` in-place reflecting the new filename set and the transitioned RFC's new Status. Stage the refreshed README with the same commit.
135
+
136
+ Update the "Last reviewed" line on `docs/rfcs/README.md` per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to `manage-problem` SKILL.md Step 5) so a single-pass agent reading this Step does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (origin failure mode: iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the equivalent rotation on `docs/problems/README.md` in 2 of 9 transition-bearing iters). The mechanism MUST execute IN ORDER:
137
+
138
+ 1. **Read** line 3 of `docs/rfcs/README.md`: `awk 'NR==3' docs/rfcs/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
139
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/rfcs/README-history.md` (created on first rotation) under a `## YYYY-MM-DD` heading. Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
140
+ 3. **Rewrite** line 3 of `docs/rfcs/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `RFC-<NNN> <status> — <one-line summary>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
141
+ 4. **Stage both** — `git add docs/rfcs/README.md docs/rfcs/README-history.md` so the same single commit per ADR-014 captures both files.
142
+
143
+ Canonical rationale anchor: `manage-problem` SKILL.md Step 5 § Last-reviewed line discipline (P134). The discipline applies identically across `docs/problems/README.md`, `docs/rfcs/README.md`, and `docs/stories/README.md` (only the target index path differs). The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
135
144
 
136
145
  #### Reverse trace on driving problem(s) (skill-side primary surface)
137
146
 
@@ -124,7 +124,14 @@ The auto-transition logic fires in two contexts:
124
124
 
125
125
  After rename + Edit + re-stage, regenerate `docs/stories/README.md` Story Rankings + Done tables in-place reflecting the new filename set and the transitioned story's new Status. Stage the refreshed README with the same commit.
126
126
 
127
- The "Last reviewed" line on `docs/stories/README.md` follows the same P134 truncation discipline as `docs/problems/README.md`: single most-recent fragment on line 3; soft cap 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
127
+ Update the "Last reviewed" line on `docs/stories/README.md` per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to `manage-problem` SKILL.md Step 5) so a single-pass agent reading this Step does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (origin failure mode: iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the equivalent rotation on `docs/problems/README.md` in 2 of 9 transition-bearing iters). The mechanism MUST execute IN ORDER:
128
+
129
+ 1. **Read** line 3 of `docs/stories/README.md`: `awk 'NR==3' docs/stories/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
130
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/stories/README-history.md` (created on first rotation) under a `## YYYY-MM-DD` heading. Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
131
+ 3. **Rewrite** line 3 of `docs/stories/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `STORY-<NNN> <status> — <one-line summary>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
132
+ 4. **Stage both** — `git add docs/stories/README.md docs/stories/README-history.md` so the same single commit per ADR-014 captures both files.
133
+
134
+ Canonical rationale anchor: `manage-problem` SKILL.md Step 5 § Last-reviewed line discipline (P134). The discipline applies identically across `docs/problems/README.md`, `docs/rfcs/README.md`, and `docs/stories/README.md` (only the target index path differs). The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
128
135
 
129
136
  #### Reverse trace on driving problem(s), JTBD(s), RFC(s), story-map(s) — skill-side primary surface
130
137
 
@@ -371,7 +371,14 @@ When `docs/problems/.upstream-cache.json` is missing OR has `last_checked: null`
371
371
  ...
372
372
  ```
373
373
 
374
- Apply the **Last-reviewed line discipline (P134)** contract documented in `manage-problem` SKILL.md Step 5 line 3 carries ONE most-recent fragment naming the meaningful state change in this refresh (auto-transitions fired, priority flips, newly-stale tickets); displaced prior fragments rotate to `docs/problems/README-history.md` (forward-chronology archive, soft cap 1024 bytes per fragment, hard ceiling 5120 bytes per ADR-040 Tier 3 envelope, surfaced advisory-only by `packages/itil/scripts/check-problems-readme-budget.sh`). When the rotation displaces prior content, the staged file set MUST include both `docs/problems/README.md` AND `docs/problems/README-history.md` per ADR-014 single-commit grain.
374
+ Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-reference to `manage-problem` SKILL.md Step 5) so a single-pass agent reading this review refresh does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
375
+
376
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
377
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
378
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment naming the meaningful state change in this refresh (e.g. `auto-transitions fired: P<NNN> → KE`, priority flips, newly-stale tickets). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope; advisory-only enforcement via `packages/itil/scripts/check-problems-readme-budget.sh`.
379
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 captures both files.
380
+
381
+ Canonical rationale anchor: `manage-problem` SKILL.md Step 5 § Last-reviewed line discipline (P134). The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
375
382
 
376
383
  ### 6. Commit the refresh
377
384
 
@@ -206,7 +206,14 @@ The refresh uses the same rendering rules as `/wr-itil:review-problems` Step 9e
206
206
 
207
207
  1. After renaming + Editing + `git add`-ing the transitioned ticket file (per the staging-trap rule above), regenerate `docs/problems/README.md` in-place reflecting the new filename set and the transitioned ticket's new Status.
208
208
  2. `git add docs/problems/README.md` — stage the refreshed README with the same commit as the transition.
209
- 3. Update the "Last reviewed" line per the **Last-reviewed line discipline (P134)** contract documented in `manage-problem` SKILL.md Step 5 name the transition as the most-recent fragment (e.g. `P<NNN> <status> <one-line fix summary>`); displaced prior fragments rotate to `docs/problems/README-history.md` (forward-chronology archive, soft cap 1024 bytes per fragment, hard ceiling 5120 bytes per ADR-040 Tier 3 envelope, surfaced advisory-only by `packages/itil/scripts/check-problems-readme-budget.sh`). When the rotation displaces prior content, the staged file set MUST include both `docs/problems/README.md` AND `docs/problems/README-history.md` per ADR-014 single-commit grain.
209
+ 3. Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-document reference to `manage-problem` SKILL.md Step 5) so a single-pass agent reading this Step 7 does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). The mechanism MUST execute IN ORDER:
210
+
211
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
212
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
213
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new fragment of form `> Last reviewed: YYYY-MM-DD **<event>** — <one-line summary>` (e.g. `P<NNN> <status> — <one-line fix summary>`). Soft cap ≤ 1024 bytes per fragment; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope; advisory-only enforcement via `packages/itil/scripts/check-problems-readme-budget.sh`.
214
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single commit per ADR-014 single-commit grain captures both files.
215
+
216
+ Canonical rationale anchor: `manage-problem` SKILL.md Step 5 § Last-reviewed line discipline (P134). The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
210
217
 
211
218
  ### 8. Commit per ADR-014
212
219
 
@@ -216,3 +216,70 @@ setup() {
216
216
  run grep -inE "<NNN>|ticket.{0,5}ID|ID.*argument|data parameter" "$SKILL_FILE"
217
217
  [ "$status" -eq 0 ]
218
218
  }
219
+
220
+ # ──────────────────────────────────────────────────────────────────────
221
+ # P331 — Inline P134 rotation mechanism (anti-skip contract)
222
+ #
223
+ # Before P331's fix, the P134 line-3 rotation discipline was documented
224
+ # at this skill's Step 7 (and 5 sibling surfaces) as a single-sentence
225
+ # cross-document reference of shape:
226
+ #
227
+ # "Update the 'Last reviewed' line per the **Last-reviewed line
228
+ # discipline (P134)** contract documented in `manage-problem`
229
+ # SKILL.md Step 5"
230
+ #
231
+ # Agents reading the SKILL in a single-pass execution context did not
232
+ # cross-navigate to manage-problem Step 5 and executed the obvious
233
+ # "regenerate README.md" + "git add" steps without first archiving the
234
+ # displaced line 3 to README-history.md. Iter-7 + iter-8 of 2026-05-30's
235
+ # AFK work-problems session silently skipped the rotation in 2 of 9
236
+ # transition-bearing iters (~22%).
237
+ #
238
+ # Positive control: reconcile-readme Step 5 inlines the same 3-step
239
+ # Mechanism as an enumerated numbered list AT the execution site — that
240
+ # surface fires correctly. The asymmetry confirms the bug class is
241
+ # "cross-document reference at execution sites" vs "inlined mechanism".
242
+ #
243
+ # The fix elevates the rotation from a one-liner to a 4-step inline
244
+ # Mechanism block (Read line 3 / Append-if-non-empty BEFORE rewrite /
245
+ # Rewrite line 3 / Stage both). The assertions below lock the inline
246
+ # block's presence at this skill's Step 7 execution site so future
247
+ # refactors don't silently regress to the cross-doc one-liner.
248
+
249
+ @test "SKILL.md inlines the P134 rotation Mechanism Read step at Step 7 (P331)" {
250
+ # The mechanism must explicitly call out reading line 3 before
251
+ # rewriting it. The canonical read pattern is `awk 'NR==3'` (matching
252
+ # reconcile-readme Step 5's worked example); `head -3` or `sed -n '3p'`
253
+ # are acceptable equivalents.
254
+ run grep -iE "awk +'NR==3'|head +-3|sed +-n +'3p'|line 3.{0,40}(read|of \`docs/problems/README.md\`)" "$SKILL_FILE"
255
+ [ "$status" -eq 0 ]
256
+ }
257
+
258
+ @test "SKILL.md inlines the P134 rotation Mechanism Append-BEFORE-Rewrite ordering (P331)" {
259
+ # The ordering rule is load-bearing: the displaced line 3 MUST be
260
+ # appended to README-history.md BEFORE the Edit-tool rewrite of line
261
+ # 3. Without this rule, the Edit replace destroys the displaced
262
+ # content. The assertion checks for explicit ordering language
263
+ # (BEFORE / before rewriting / before step 3) co-located with the
264
+ # README-history.md target.
265
+ run grep -inE "(BEFORE|before).{0,80}(rewrit|step 3|Edit)" "$SKILL_FILE"
266
+ [ "$status" -eq 0 ]
267
+ }
268
+
269
+ @test "SKILL.md cites README-history.md as the rotation archive target at Step 7 (P331)" {
270
+ # The archive sibling docs/problems/README-history.md is named at the
271
+ # rotation step. Without an explicit named target, the agent has no
272
+ # destination to append to.
273
+ run grep -E "README-history\.md" "$SKILL_FILE"
274
+ [ "$status" -eq 0 ]
275
+ }
276
+
277
+ @test "SKILL.md cites P331 + P134 at the inlined rotation mechanism (traceability per ADR-037)" {
278
+ # The inlined mechanism block cites P331 (this ticket) and P134
279
+ # (the originating discipline ticket) so future readers can trace
280
+ # the load-bearing rationale.
281
+ run grep -inE "P331" "$SKILL_FILE"
282
+ [ "$status" -eq 0 ]
283
+ run grep -inE "P134" "$SKILL_FILE"
284
+ [ "$status" -eq 0 ]
285
+ }
@@ -186,7 +186,14 @@ The refresh follows the same render rules as `/wr-itil:review-problems` Step 9e
186
186
  git add docs/problems/README.md
187
187
  ```
188
188
 
189
- Update the "Last reviewed" line per the **Last-reviewed line discipline (P134)** contract documented in `manage-problem` SKILL.md Step 5 name the batch as a SINGLE most-recent fragment summarising the cohort (e.g. `batch transition: P063 close, P067 close, P092 close, P094 close`); displaced prior fragments rotate to `docs/problems/README-history.md` ONCE for the entire batch, not per-pair. Soft cap 1024 bytes for the batch fragment if the cohort would exceed it, abbreviate to ID + verb only and let the per-ticket bodies carry the rationale. When the rotation displaces prior content, also `git add docs/problems/README-history.md` so the same single batch commit per ADR-014 captures both files.
189
+ Update the "Last reviewed" line per the **inline P134 rotation mechanism** below. The mechanism is inlined here at the execution site (not deferred via cross-document reference to `manage-problem` SKILL.md Step 5) so a single-pass agent reading this Step 4a does not silently skip the archive step. **Skipping the BEFORE-rewrite archive step destroys the displaced fragment and re-opens P331** (iter-7 + iter-8 of 2026-05-30's AFK work-problems session silently skipped the rotation in 2 of 9 transition-bearing iters under exactly that failure mode). At batch grain the rotation fires ONCE for the entire batch (not per-pair) but the per-pair semantics are otherwise identical to the singular's Step 7. The mechanism MUST execute IN ORDER:
190
+
191
+ 1. **Read** line 3 of `docs/problems/README.md`: `awk 'NR==3' docs/problems/README.md` (`head -3 | tail -1` or `sed -n '3p'` are acceptable equivalents).
192
+ 2. **Append-if-non-empty (BEFORE step 3, not after)** — if line 3 is non-empty AND not a same-session same-verb near-duplicate of the new batch fragment, append the existing line 3 verbatim to `docs/problems/README-history.md` under a `## YYYY-MM-DD` heading (creating the heading on first append for that date; subsequent same-day appends nest under the existing heading). Run this BEFORE the Edit-tool rewrite in step 3 — Edit's replace pattern destroys the displaced content otherwise.
193
+ 3. **Rewrite** line 3 of `docs/problems/README.md` with the new batch fragment of form `> Last reviewed: YYYY-MM-DD **batch transition** — P<NNN> <status>, P<NNN> <status>, …` (e.g. `> Last reviewed: 2026-06-01 **batch transition** — P063 close, P067 close, P092 close, P094 close`). Soft cap ≤ 1024 bytes per fragment — if the cohort would exceed it, abbreviate to ID + verb only and let the per-ticket bodies carry the rationale; hard ceiling 5120 bytes per ADR-040 Tier 3 envelope.
194
+ 4. **Stage both** — `git add docs/problems/README.md docs/problems/README-history.md` so the same single batch commit per ADR-014 captures both files.
195
+
196
+ Canonical rationale anchor: `manage-problem` SKILL.md Step 5 § Last-reviewed line discipline (P134). The cross-reference is preserved for the "why"; the "what" is inlined above for execution-time legibility per P331.
190
197
 
191
198
  **4b. Commit gate (per ADR-014).**
192
199
 
@@ -274,3 +274,58 @@ setup() {
274
274
  [ "$singular_count" -ge 1 ]
275
275
  [ "$plural_count" -ge 1 ]
276
276
  }
277
+
278
+ # ──────────────────────────────────────────────────────────────────────
279
+ # P331 — Inline P134 rotation mechanism (anti-skip contract; plural mirror)
280
+ #
281
+ # See the singular contract bats for the full rationale. At batch grain
282
+ # the rotation still fires ONCE per batch (per Step 4a) — but the
283
+ # Mechanism prose must be inlined here at the execution site too, so a
284
+ # contract-literal agent invoking transition-problems doesn't skip the
285
+ # archive step under the same one-liner-cross-doc failure mode P331
286
+ # captured at the singular's Step 7. The cross-skill drift between
287
+ # singular and plural is detected by the shared-substring assertions
288
+ # below — if the singular inlines the mechanism but the plural still
289
+ # carries the one-liner, the assertions fail.
290
+
291
+ @test "SKILL.md inlines the P134 rotation Mechanism Read step at Step 4a (P331)" {
292
+ # Same Read pattern as the singular — `awk 'NR==3'` or equivalent
293
+ # before the line 3 rewrite. Inline mechanism at the execution site
294
+ # so the rotation cannot be silently skipped on the cross-doc trip
295
+ # to manage-problem Step 5.
296
+ run grep -iE "awk +'NR==3'|head +-3|sed +-n +'3p'|line 3.{0,40}(read|of \`docs/problems/README.md\`)" "$SKILL_FILE"
297
+ [ "$status" -eq 0 ]
298
+ }
299
+
300
+ @test "SKILL.md inlines the P134 rotation Mechanism Append-BEFORE-Rewrite ordering (P331)" {
301
+ # Ordering rule load-bearing per the singular — see the singular's
302
+ # rationale comment. Plural inherits the rule at batch grain.
303
+ run grep -inE "(BEFORE|before).{0,80}(rewrit|step 3|Edit)" "$SKILL_FILE"
304
+ [ "$status" -eq 0 ]
305
+ }
306
+
307
+ @test "SKILL.md cites README-history.md as the rotation archive target at Step 4a (P331)" {
308
+ run grep -E "README-history\.md" "$SKILL_FILE"
309
+ [ "$status" -eq 0 ]
310
+ }
311
+
312
+ @test "SKILL.md cites P331 + P134 at the inlined rotation mechanism (traceability per ADR-037)" {
313
+ run grep -inE "P331" "$SKILL_FILE"
314
+ [ "$status" -eq 0 ]
315
+ run grep -inE "P134" "$SKILL_FILE"
316
+ [ "$status" -eq 0 ]
317
+ }
318
+
319
+ @test "SKILL.md and singular SKILL.md share the P134 Read-step pattern (drift detection)" {
320
+ # The canonical Read-step pattern `awk 'NR==3'` (or equivalent) must
321
+ # appear in BOTH the singular SKILL.md and this plural SKILL.md.
322
+ # Inline-copy drift between the two re-opens P331; this assertion
323
+ # surfaces the drift as a contract failure.
324
+ [ -f "$SINGULAR_SKILL_FILE" ]
325
+ run grep -cE "awk +'NR==3'|head +-3|sed +-n +'3p'" "$SINGULAR_SKILL_FILE"
326
+ singular_count="$output"
327
+ run grep -cE "awk +'NR==3'|head +-3|sed +-n +'3p'" "$SKILL_FILE"
328
+ plural_count="$output"
329
+ [ "$singular_count" -ge 1 ]
330
+ [ "$plural_count" -ge 1 ]
331
+ }