@windyroad/itil 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "wr-itil",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "ITIL-aligned IT service management for Claude Code"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/itil",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
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"
@@ -14,6 +14,28 @@ The user is AFK during this process, so every decision point that would normally
14
14
 
15
15
  Each iteration is one cycle of: scan backlog, pick highest-WSJF problem, work it, report result. The loop continues until a stop condition is met.
16
16
 
17
+ ### Step 0: Preflight (per ADR-019)
18
+
19
+ Before opening the work loop, reconcile local state with origin so the orchestrator does not iterate against a stale backlog or create tickets with IDs that collide with parallel sessions (P040).
20
+
21
+ **Mechanism:**
22
+
23
+ 1. Run `git fetch origin`.
24
+ 2. Compare local `HEAD` with `origin/<base>` (default `main`; otherwise the branch the user is on).
25
+ 3. Branch on the divergence shape:
26
+
27
+ | Local vs origin | Action |
28
+ |---|---|
29
+ | HEAD at or ahead of origin/<base> | Proceed to Step 1 |
30
+ | origin/<base> ahead, local has no unpushed commits (pure fast-forward) | Run `git pull --ff-only` non-interactively. Log the count of pulled commits in the AFK iteration log. Proceed to Step 1. |
31
+ | origin/<base> ahead, local has unpushed commits (non-fast-forward) | STOP the loop. Report the divergence with `git log --oneline HEAD..origin/<base>` and `git log --oneline origin/<base>..HEAD`. Do NOT attempt to rebase or merge non-interactively — that is a judgment call the persona forbids in AFK mode. |
32
+
33
+ **Network failure**: if `git fetch origin` returns a network error, stop and report. Default behaviour is fail-closed — the user can retry when network is restored.
34
+
35
+ **Non-interactive authorisation**: per ADR-013 Rule 6, `git fetch origin` and `git pull --ff-only` are policy-authorised actions (no semantic merge, no destructive overwrite). `git pull --rebase`, `git merge`, and any operation that resolves conflicts are NOT policy-authorised — they require user input.
36
+
37
+ **Cross-cutting**: this rule applies to every AFK orchestrator skill. The next-ID collision guard (ADR-019 confirmation criterion 2) belongs in the ticket-creator skills (`manage-problem` and `wr-architect:create-adr`), not here — see the related problem ticket for that work.
38
+
17
39
  ### Step 1: Scan the backlog
18
40
 
19
41
  Read `docs/problems/README.md` if it exists and is fresh (check via git history — see manage-problem step 9 for the cache freshness check). If stale or missing, scan all `.open.md` and `.known-error.md` files in `docs/problems/`, extract their WSJF scores, and rank them.
@@ -134,6 +156,7 @@ When `AskUserQuestion` is unavailable or the user is AFK, the skill (and the del
134
156
  | Commit when risk within appetite | Auto-commit (manage-problem step 9e fallback) |
135
157
  | Commit when risk above appetite | Skip commit, report uncommitted state |
136
158
  | Pipeline risk at appetite (push or release >= 4/25) | Drain release queue (`push:watch` then `release:watch`) before next iteration — per ADR-018 (Step 6.5) |
159
+ | Origin diverged before start | Pull `--ff-only` if trivial; stop with report (`git log HEAD..origin/<base>` and reverse) if non-fast-forward — per ADR-019 (Step 0) |
137
160
  | Fix verification needed | Skip problem, add to "needs verification" list |
138
161
 
139
162
  ## Edge Cases
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env bats
2
+ # Doc-lint guard: work-problems SKILL.md must include the preflight
3
+ # (fetch-origin + divergence handling) per ADR-019.
4
+ #
5
+ # Structural assertion — Permitted Exception to the source-grep ban (ADR-005 / P011).
6
+ # These tests assert that the skill specification document contains the
7
+ # preflight step so the AFK orchestrator does not iterate against a stale
8
+ # local backlog when origin/<base> has advanced.
9
+ #
10
+ # Cross-reference:
11
+ # P040 (work-problems does not fetch origin before starting)
12
+ # ADR-019 (AFK orchestrator preflight)
13
+ # @jtbd JTBD-006 (Progress the Backlog While I'm Away)
14
+
15
+ setup() {
16
+ SKILL_DIR="$(cd "$(dirname "$BATS_TEST_FILENAME")/.." && pwd)"
17
+ SKILL_FILE="${SKILL_DIR}/SKILL.md"
18
+ }
19
+
20
+ @test "SKILL.md cites ADR-019 (preflight)" {
21
+ # ADR-019 confirmation criterion: skill must reference the ADR.
22
+ run grep -n "ADR-019" "$SKILL_FILE"
23
+ [ "$status" -eq 0 ]
24
+ }
25
+
26
+ @test "SKILL.md preflight runs git fetch origin" {
27
+ # ADR-019 mechanism: must run `git fetch origin` before opening the
28
+ # work loop.
29
+ run grep -n "git fetch origin" "$SKILL_FILE"
30
+ [ "$status" -eq 0 ]
31
+ }
32
+
33
+ @test "SKILL.md preflight uses git pull --ff-only on trivial divergence" {
34
+ # ADR-019 mechanism: trivial fast-forward is policy-authorised; non-ff is
35
+ # not. The skill must cite --ff-only to prevent merge attempts.
36
+ run grep -n "ff-only" "$SKILL_FILE"
37
+ [ "$status" -eq 0 ]
38
+ }
39
+
40
+ @test "SKILL.md preflight stops the loop on non-fast-forward divergence" {
41
+ # Confirmation: divergence handling must include a stop-with-report path,
42
+ # not a silent retry or merge.
43
+ run grep -niE "non-fast-forward|non-ff" "$SKILL_FILE"
44
+ [ "$status" -eq 0 ]
45
+ }
46
+
47
+ @test "SKILL.md preflight has a discrete step before backlog scan" {
48
+ # The preflight should appear as a discrete step (e.g. Step 0 — Preflight)
49
+ # so it is not buried in prose.
50
+ run grep -niE "step 0|preflight" "$SKILL_FILE"
51
+ [ "$status" -eq 0 ]
52
+ }
53
+
54
+ @test "SKILL.md Non-Interactive Decision Making table covers origin divergence" {
55
+ # ADR-019 confirmation: the non-interactive defaults table must include a
56
+ # row for the divergence decision.
57
+ run grep -niE "Origin diverged|origin.*divergence|fast-forward" "$SKILL_FILE"
58
+ [ "$status" -eq 0 ]
59
+ }
60
+
61
+ @test "SKILL.md explicitly forbids non-interactive merge/rebase remediation" {
62
+ # ADR-019 forbids non-interactive rebase/merge attempts. The skill must
63
+ # negate these (e.g. "Do NOT attempt to rebase or merge" or "are NOT
64
+ # policy-authorised") rather than silently allow them. We assert the
65
+ # negation appears, not that the words are absent — discussing forbidden
66
+ # operations in the negative is exactly what the ADR requires.
67
+ run grep -niE "Do NOT attempt to rebase or merge|NOT policy-authorised" "$SKILL_FILE"
68
+ [ "$status" -eq 0 ]
69
+ }