@windyroad/itil 0.35.3-preview.352 → 0.35.4-preview.357
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 +137 -135
- package/README.md +1 -1
- package/package.json +1 -1
- package/scripts/plugin-maturity-populate.sh +31 -1
- package/scripts/test/plugin-maturity-doc-lint.bats +63 -3
- package/scripts/test/plugin-maturity-populate.bats +141 -1
- package/scripts/test/plugin-maturity-render.bats +58 -0
|
@@ -2,479 +2,481 @@
|
|
|
2
2
|
"description": "ITIL-aligned IT service management for Claude Code",
|
|
3
3
|
"maturity": {
|
|
4
4
|
"band": "Experimental",
|
|
5
|
-
"
|
|
5
|
+
"bootstrapping": true,
|
|
6
6
|
"hooks": {
|
|
7
7
|
"itil-assistant-output-gate": {
|
|
8
8
|
"band": "Experimental",
|
|
9
|
-
"computed_at": "2026-05-
|
|
9
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
10
10
|
"evidence": {
|
|
11
11
|
"breaking_change_age_days": null,
|
|
12
|
-
"closed_tickets_window":
|
|
13
|
-
"days_shipped":
|
|
12
|
+
"closed_tickets_window": 99,
|
|
13
|
+
"days_shipped": 33,
|
|
14
14
|
"invocations_30d": null
|
|
15
15
|
},
|
|
16
16
|
"schema_version": "2.0"
|
|
17
17
|
},
|
|
18
18
|
"itil-assistant-output-review": {
|
|
19
19
|
"band": "Experimental",
|
|
20
|
-
"computed_at": "2026-05-
|
|
20
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
21
21
|
"evidence": {
|
|
22
22
|
"breaking_change_age_days": null,
|
|
23
|
-
"closed_tickets_window":
|
|
24
|
-
"days_shipped":
|
|
23
|
+
"closed_tickets_window": 99,
|
|
24
|
+
"days_shipped": 33,
|
|
25
25
|
"invocations_30d": null
|
|
26
26
|
},
|
|
27
27
|
"schema_version": "2.0"
|
|
28
28
|
},
|
|
29
29
|
"itil-bash-polling-antipattern-detect": {
|
|
30
30
|
"band": "Experimental",
|
|
31
|
-
"computed_at": "2026-05-
|
|
31
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
32
32
|
"evidence": {
|
|
33
33
|
"breaking_change_age_days": null,
|
|
34
|
-
"closed_tickets_window":
|
|
35
|
-
"days_shipped":
|
|
34
|
+
"closed_tickets_window": 99,
|
|
35
|
+
"days_shipped": 33,
|
|
36
36
|
"invocations_30d": null
|
|
37
37
|
},
|
|
38
38
|
"schema_version": "2.0"
|
|
39
39
|
},
|
|
40
40
|
"itil-changeset-discipline": {
|
|
41
41
|
"band": "Experimental",
|
|
42
|
-
"computed_at": "2026-05-
|
|
42
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
43
43
|
"evidence": {
|
|
44
44
|
"breaking_change_age_days": null,
|
|
45
|
-
"closed_tickets_window":
|
|
46
|
-
"days_shipped":
|
|
45
|
+
"closed_tickets_window": 99,
|
|
46
|
+
"days_shipped": 33,
|
|
47
47
|
"invocations_30d": null
|
|
48
48
|
},
|
|
49
49
|
"schema_version": "2.0"
|
|
50
50
|
},
|
|
51
51
|
"itil-claude-space-protection": {
|
|
52
52
|
"band": "Experimental",
|
|
53
|
-
"computed_at": "2026-05-
|
|
53
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
54
54
|
"evidence": {
|
|
55
55
|
"breaking_change_age_days": null,
|
|
56
|
-
"closed_tickets_window":
|
|
57
|
-
"days_shipped":
|
|
56
|
+
"closed_tickets_window": 99,
|
|
57
|
+
"days_shipped": 33,
|
|
58
58
|
"invocations_30d": null
|
|
59
59
|
},
|
|
60
60
|
"schema_version": "2.0"
|
|
61
61
|
},
|
|
62
62
|
"itil-correction-detect": {
|
|
63
63
|
"band": "Experimental",
|
|
64
|
-
"computed_at": "2026-05-
|
|
64
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
65
65
|
"evidence": {
|
|
66
66
|
"breaking_change_age_days": null,
|
|
67
|
-
"closed_tickets_window":
|
|
68
|
-
"days_shipped":
|
|
67
|
+
"closed_tickets_window": 99,
|
|
68
|
+
"days_shipped": 33,
|
|
69
69
|
"invocations_30d": null
|
|
70
70
|
},
|
|
71
71
|
"schema_version": "2.0"
|
|
72
72
|
},
|
|
73
73
|
"itil-fictional-defer-detect": {
|
|
74
74
|
"band": "Experimental",
|
|
75
|
-
"computed_at": "2026-05-
|
|
75
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
76
76
|
"evidence": {
|
|
77
77
|
"breaking_change_age_days": null,
|
|
78
|
-
"closed_tickets_window":
|
|
79
|
-
"days_shipped":
|
|
78
|
+
"closed_tickets_window": 99,
|
|
79
|
+
"days_shipped": 33,
|
|
80
80
|
"invocations_30d": null
|
|
81
81
|
},
|
|
82
82
|
"schema_version": "2.0"
|
|
83
83
|
},
|
|
84
84
|
"itil-mid-loop-ask-detect": {
|
|
85
85
|
"band": "Experimental",
|
|
86
|
-
"computed_at": "2026-05-
|
|
86
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
87
87
|
"evidence": {
|
|
88
88
|
"breaking_change_age_days": null,
|
|
89
|
-
"closed_tickets_window":
|
|
90
|
-
"days_shipped":
|
|
89
|
+
"closed_tickets_window": 99,
|
|
90
|
+
"days_shipped": 33,
|
|
91
91
|
"invocations_30d": null
|
|
92
92
|
},
|
|
93
93
|
"schema_version": "2.0"
|
|
94
94
|
},
|
|
95
95
|
"itil-pending-questions-surface": {
|
|
96
96
|
"band": "Experimental",
|
|
97
|
-
"computed_at": "2026-05-
|
|
97
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
98
98
|
"evidence": {
|
|
99
99
|
"breaking_change_age_days": null,
|
|
100
|
-
"closed_tickets_window":
|
|
101
|
-
"days_shipped":
|
|
100
|
+
"closed_tickets_window": 99,
|
|
101
|
+
"days_shipped": 33,
|
|
102
102
|
"invocations_30d": null
|
|
103
103
|
},
|
|
104
104
|
"schema_version": "2.0"
|
|
105
105
|
},
|
|
106
106
|
"itil-readme-refresh-discipline": {
|
|
107
107
|
"band": "Experimental",
|
|
108
|
-
"computed_at": "2026-05-
|
|
108
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
109
109
|
"evidence": {
|
|
110
110
|
"breaking_change_age_days": null,
|
|
111
|
-
"closed_tickets_window":
|
|
112
|
-
"days_shipped":
|
|
111
|
+
"closed_tickets_window": 99,
|
|
112
|
+
"days_shipped": 33,
|
|
113
113
|
"invocations_30d": null
|
|
114
114
|
},
|
|
115
115
|
"schema_version": "2.0"
|
|
116
116
|
},
|
|
117
117
|
"itil-rfc-trailer-advisory": {
|
|
118
118
|
"band": "Experimental",
|
|
119
|
-
"computed_at": "2026-05-
|
|
119
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
120
120
|
"evidence": {
|
|
121
121
|
"breaking_change_age_days": null,
|
|
122
|
-
"closed_tickets_window":
|
|
123
|
-
"days_shipped":
|
|
122
|
+
"closed_tickets_window": 99,
|
|
123
|
+
"days_shipped": 33,
|
|
124
124
|
"invocations_30d": null
|
|
125
125
|
},
|
|
126
126
|
"schema_version": "2.0"
|
|
127
127
|
},
|
|
128
128
|
"itil-runtime-sid-marker": {
|
|
129
129
|
"band": "Experimental",
|
|
130
|
-
"computed_at": "2026-05-
|
|
130
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
131
131
|
"evidence": {
|
|
132
132
|
"breaking_change_age_days": null,
|
|
133
|
-
"closed_tickets_window":
|
|
134
|
-
"days_shipped":
|
|
133
|
+
"closed_tickets_window": 99,
|
|
134
|
+
"days_shipped": 33,
|
|
135
135
|
"invocations_30d": null
|
|
136
136
|
},
|
|
137
137
|
"schema_version": "2.0"
|
|
138
138
|
},
|
|
139
139
|
"manage-problem-enforce-create": {
|
|
140
140
|
"band": "Experimental",
|
|
141
|
-
"computed_at": "2026-05-
|
|
141
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
142
142
|
"evidence": {
|
|
143
143
|
"breaking_change_age_days": null,
|
|
144
|
-
"closed_tickets_window":
|
|
145
|
-
"days_shipped":
|
|
144
|
+
"closed_tickets_window": 99,
|
|
145
|
+
"days_shipped": 33,
|
|
146
146
|
"invocations_30d": null
|
|
147
147
|
},
|
|
148
148
|
"schema_version": "2.0"
|
|
149
149
|
},
|
|
150
150
|
"p057-staging-trap-detect": {
|
|
151
151
|
"band": "Experimental",
|
|
152
|
-
"computed_at": "2026-05-
|
|
152
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
153
153
|
"evidence": {
|
|
154
154
|
"breaking_change_age_days": null,
|
|
155
|
-
"closed_tickets_window":
|
|
156
|
-
"days_shipped":
|
|
155
|
+
"closed_tickets_window": 99,
|
|
156
|
+
"days_shipped": 33,
|
|
157
157
|
"invocations_30d": null
|
|
158
158
|
},
|
|
159
159
|
"schema_version": "2.0"
|
|
160
160
|
},
|
|
161
161
|
"pre-publish-intake-gate": {
|
|
162
162
|
"band": "Experimental",
|
|
163
|
-
"computed_at": "2026-05-
|
|
163
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
164
164
|
"evidence": {
|
|
165
165
|
"breaking_change_age_days": null,
|
|
166
|
-
"closed_tickets_window":
|
|
167
|
-
"days_shipped":
|
|
166
|
+
"closed_tickets_window": 99,
|
|
167
|
+
"days_shipped": 33,
|
|
168
168
|
"invocations_30d": null
|
|
169
169
|
},
|
|
170
170
|
"schema_version": "2.0"
|
|
171
171
|
}
|
|
172
172
|
},
|
|
173
|
+
"rollup_invocations_30d": 327,
|
|
174
|
+
"schema_version": "2.0",
|
|
173
175
|
"skills": {
|
|
174
176
|
"capture-problem": {
|
|
175
177
|
"band": "Experimental",
|
|
176
|
-
"computed_at": "2026-05-
|
|
178
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
177
179
|
"evidence": {
|
|
178
180
|
"breaking_change_age_days": null,
|
|
179
|
-
"closed_tickets_window":
|
|
180
|
-
"days_shipped":
|
|
181
|
-
"invocations_30d":
|
|
181
|
+
"closed_tickets_window": 99,
|
|
182
|
+
"days_shipped": 33,
|
|
183
|
+
"invocations_30d": 61
|
|
182
184
|
},
|
|
183
185
|
"schema_version": "2.0"
|
|
184
186
|
},
|
|
185
187
|
"capture-rfc": {
|
|
186
188
|
"band": "Experimental",
|
|
187
|
-
"computed_at": "2026-05-
|
|
189
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
188
190
|
"evidence": {
|
|
189
191
|
"breaking_change_age_days": null,
|
|
190
|
-
"closed_tickets_window":
|
|
191
|
-
"days_shipped":
|
|
192
|
+
"closed_tickets_window": 99,
|
|
193
|
+
"days_shipped": 33,
|
|
192
194
|
"invocations_30d": 2
|
|
193
195
|
},
|
|
194
196
|
"schema_version": "2.0"
|
|
195
197
|
},
|
|
196
198
|
"capture-story": {
|
|
197
199
|
"band": "Experimental",
|
|
198
|
-
"computed_at": "2026-05-
|
|
200
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
199
201
|
"evidence": {
|
|
200
202
|
"breaking_change_age_days": null,
|
|
201
|
-
"closed_tickets_window":
|
|
202
|
-
"days_shipped":
|
|
203
|
+
"closed_tickets_window": 99,
|
|
204
|
+
"days_shipped": 33,
|
|
203
205
|
"invocations_30d": 0
|
|
204
206
|
},
|
|
205
207
|
"schema_version": "2.0"
|
|
206
208
|
},
|
|
207
209
|
"capture-story-map": {
|
|
208
210
|
"band": "Experimental",
|
|
209
|
-
"computed_at": "2026-05-
|
|
211
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
210
212
|
"evidence": {
|
|
211
213
|
"breaking_change_age_days": null,
|
|
212
|
-
"closed_tickets_window":
|
|
213
|
-
"days_shipped":
|
|
214
|
+
"closed_tickets_window": 99,
|
|
215
|
+
"days_shipped": 33,
|
|
214
216
|
"invocations_30d": 0
|
|
215
217
|
},
|
|
216
218
|
"schema_version": "2.0"
|
|
217
219
|
},
|
|
218
220
|
"check-upstream-responses": {
|
|
219
221
|
"band": "Experimental",
|
|
220
|
-
"computed_at": "2026-05-
|
|
222
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
221
223
|
"evidence": {
|
|
222
224
|
"breaking_change_age_days": null,
|
|
223
|
-
"closed_tickets_window":
|
|
224
|
-
"days_shipped":
|
|
225
|
+
"closed_tickets_window": 99,
|
|
226
|
+
"days_shipped": 33,
|
|
225
227
|
"invocations_30d": 0
|
|
226
228
|
},
|
|
227
229
|
"schema_version": "2.0"
|
|
228
230
|
},
|
|
229
231
|
"close-incident": {
|
|
230
232
|
"band": "Experimental",
|
|
231
|
-
"computed_at": "2026-05-
|
|
233
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
232
234
|
"evidence": {
|
|
233
235
|
"breaking_change_age_days": null,
|
|
234
|
-
"closed_tickets_window":
|
|
235
|
-
"days_shipped":
|
|
236
|
+
"closed_tickets_window": 99,
|
|
237
|
+
"days_shipped": 33,
|
|
236
238
|
"invocations_30d": 0
|
|
237
239
|
},
|
|
238
240
|
"schema_version": "2.0"
|
|
239
241
|
},
|
|
240
242
|
"link-incident": {
|
|
241
243
|
"band": "Experimental",
|
|
242
|
-
"computed_at": "2026-05-
|
|
244
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
243
245
|
"evidence": {
|
|
244
246
|
"breaking_change_age_days": null,
|
|
245
|
-
"closed_tickets_window":
|
|
246
|
-
"days_shipped":
|
|
247
|
+
"closed_tickets_window": 99,
|
|
248
|
+
"days_shipped": 33,
|
|
247
249
|
"invocations_30d": 0
|
|
248
250
|
},
|
|
249
251
|
"schema_version": "2.0"
|
|
250
252
|
},
|
|
251
253
|
"list-incidents": {
|
|
252
254
|
"band": "Experimental",
|
|
253
|
-
"computed_at": "2026-05-
|
|
255
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
254
256
|
"evidence": {
|
|
255
257
|
"breaking_change_age_days": null,
|
|
256
|
-
"closed_tickets_window":
|
|
257
|
-
"days_shipped":
|
|
258
|
+
"closed_tickets_window": 99,
|
|
259
|
+
"days_shipped": 33,
|
|
258
260
|
"invocations_30d": 0
|
|
259
261
|
},
|
|
260
262
|
"schema_version": "2.0"
|
|
261
263
|
},
|
|
262
264
|
"list-problems": {
|
|
263
265
|
"band": "Experimental",
|
|
264
|
-
"computed_at": "2026-05-
|
|
266
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
265
267
|
"evidence": {
|
|
266
268
|
"breaking_change_age_days": null,
|
|
267
|
-
"closed_tickets_window":
|
|
268
|
-
"days_shipped":
|
|
269
|
+
"closed_tickets_window": 99,
|
|
270
|
+
"days_shipped": 33,
|
|
269
271
|
"invocations_30d": 1
|
|
270
272
|
},
|
|
271
273
|
"schema_version": "2.0"
|
|
272
274
|
},
|
|
273
275
|
"list-stories": {
|
|
274
276
|
"band": "Experimental",
|
|
275
|
-
"computed_at": "2026-05-
|
|
277
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
276
278
|
"evidence": {
|
|
277
279
|
"breaking_change_age_days": null,
|
|
278
|
-
"closed_tickets_window":
|
|
279
|
-
"days_shipped":
|
|
280
|
+
"closed_tickets_window": 99,
|
|
281
|
+
"days_shipped": 33,
|
|
280
282
|
"invocations_30d": 0
|
|
281
283
|
},
|
|
282
284
|
"schema_version": "2.0"
|
|
283
285
|
},
|
|
284
286
|
"list-story-maps": {
|
|
285
287
|
"band": "Experimental",
|
|
286
|
-
"computed_at": "2026-05-
|
|
288
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
287
289
|
"evidence": {
|
|
288
290
|
"breaking_change_age_days": null,
|
|
289
|
-
"closed_tickets_window":
|
|
290
|
-
"days_shipped":
|
|
291
|
+
"closed_tickets_window": 99,
|
|
292
|
+
"days_shipped": 33,
|
|
291
293
|
"invocations_30d": 0
|
|
292
294
|
},
|
|
293
295
|
"schema_version": "2.0"
|
|
294
296
|
},
|
|
295
297
|
"manage-incident": {
|
|
296
298
|
"band": "Experimental",
|
|
297
|
-
"computed_at": "2026-05-
|
|
299
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
298
300
|
"evidence": {
|
|
299
301
|
"breaking_change_age_days": null,
|
|
300
|
-
"closed_tickets_window":
|
|
301
|
-
"days_shipped":
|
|
302
|
+
"closed_tickets_window": 99,
|
|
303
|
+
"days_shipped": 33,
|
|
302
304
|
"invocations_30d": 1
|
|
303
305
|
},
|
|
304
306
|
"schema_version": "2.0"
|
|
305
307
|
},
|
|
306
308
|
"manage-problem": {
|
|
307
309
|
"band": "Alpha",
|
|
308
|
-
"computed_at": "2026-05-
|
|
310
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
309
311
|
"evidence": {
|
|
310
312
|
"breaking_change_age_days": null,
|
|
311
|
-
"closed_tickets_window":
|
|
312
|
-
"days_shipped":
|
|
313
|
-
"invocations_30d":
|
|
313
|
+
"closed_tickets_window": 99,
|
|
314
|
+
"days_shipped": 33,
|
|
315
|
+
"invocations_30d": 148
|
|
314
316
|
},
|
|
315
317
|
"schema_version": "2.0"
|
|
316
318
|
},
|
|
317
319
|
"manage-rfc": {
|
|
318
320
|
"band": "Experimental",
|
|
319
|
-
"computed_at": "2026-05-
|
|
321
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
320
322
|
"evidence": {
|
|
321
323
|
"breaking_change_age_days": null,
|
|
322
|
-
"closed_tickets_window":
|
|
323
|
-
"days_shipped":
|
|
324
|
+
"closed_tickets_window": 99,
|
|
325
|
+
"days_shipped": 33,
|
|
324
326
|
"invocations_30d": 2
|
|
325
327
|
},
|
|
326
328
|
"schema_version": "2.0"
|
|
327
329
|
},
|
|
328
330
|
"manage-story": {
|
|
329
331
|
"band": "Experimental",
|
|
330
|
-
"computed_at": "2026-05-
|
|
332
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
331
333
|
"evidence": {
|
|
332
334
|
"breaking_change_age_days": null,
|
|
333
|
-
"closed_tickets_window":
|
|
334
|
-
"days_shipped":
|
|
335
|
+
"closed_tickets_window": 99,
|
|
336
|
+
"days_shipped": 33,
|
|
335
337
|
"invocations_30d": 0
|
|
336
338
|
},
|
|
337
339
|
"schema_version": "2.0"
|
|
338
340
|
},
|
|
339
341
|
"manage-story-map": {
|
|
340
342
|
"band": "Experimental",
|
|
341
|
-
"computed_at": "2026-05-
|
|
343
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
342
344
|
"evidence": {
|
|
343
345
|
"breaking_change_age_days": null,
|
|
344
|
-
"closed_tickets_window":
|
|
345
|
-
"days_shipped":
|
|
346
|
+
"closed_tickets_window": 99,
|
|
347
|
+
"days_shipped": 33,
|
|
346
348
|
"invocations_30d": 0
|
|
347
349
|
},
|
|
348
350
|
"schema_version": "2.0"
|
|
349
351
|
},
|
|
350
352
|
"mitigate-incident": {
|
|
351
353
|
"band": "Experimental",
|
|
352
|
-
"computed_at": "2026-05-
|
|
354
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
353
355
|
"evidence": {
|
|
354
356
|
"breaking_change_age_days": null,
|
|
355
|
-
"closed_tickets_window":
|
|
356
|
-
"days_shipped":
|
|
357
|
+
"closed_tickets_window": 99,
|
|
358
|
+
"days_shipped": 33,
|
|
357
359
|
"invocations_30d": 3
|
|
358
360
|
},
|
|
359
361
|
"schema_version": "2.0"
|
|
360
362
|
},
|
|
361
363
|
"reconcile-readme": {
|
|
362
364
|
"band": "Experimental",
|
|
363
|
-
"computed_at": "2026-05-
|
|
365
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
364
366
|
"evidence": {
|
|
365
367
|
"breaking_change_age_days": null,
|
|
366
|
-
"closed_tickets_window":
|
|
367
|
-
"days_shipped":
|
|
368
|
-
"invocations_30d":
|
|
368
|
+
"closed_tickets_window": 99,
|
|
369
|
+
"days_shipped": 33,
|
|
370
|
+
"invocations_30d": 38
|
|
369
371
|
},
|
|
370
372
|
"schema_version": "2.0"
|
|
371
373
|
},
|
|
372
374
|
"reconcile-stories": {
|
|
373
375
|
"band": "Experimental",
|
|
374
|
-
"computed_at": "2026-05-
|
|
376
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
375
377
|
"evidence": {
|
|
376
378
|
"breaking_change_age_days": null,
|
|
377
|
-
"closed_tickets_window":
|
|
378
|
-
"days_shipped":
|
|
379
|
+
"closed_tickets_window": 99,
|
|
380
|
+
"days_shipped": 33,
|
|
379
381
|
"invocations_30d": 0
|
|
380
382
|
},
|
|
381
383
|
"schema_version": "2.0"
|
|
382
384
|
},
|
|
383
385
|
"reconcile-story-maps": {
|
|
384
386
|
"band": "Experimental",
|
|
385
|
-
"computed_at": "2026-05-
|
|
387
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
386
388
|
"evidence": {
|
|
387
389
|
"breaking_change_age_days": null,
|
|
388
|
-
"closed_tickets_window":
|
|
389
|
-
"days_shipped":
|
|
390
|
+
"closed_tickets_window": 99,
|
|
391
|
+
"days_shipped": 33,
|
|
390
392
|
"invocations_30d": 0
|
|
391
393
|
},
|
|
392
394
|
"schema_version": "2.0"
|
|
393
395
|
},
|
|
394
396
|
"report-upstream": {
|
|
395
397
|
"band": "Experimental",
|
|
396
|
-
"computed_at": "2026-05-
|
|
398
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
397
399
|
"evidence": {
|
|
398
400
|
"breaking_change_age_days": null,
|
|
399
|
-
"closed_tickets_window":
|
|
400
|
-
"days_shipped":
|
|
401
|
+
"closed_tickets_window": 99,
|
|
402
|
+
"days_shipped": 33,
|
|
401
403
|
"invocations_30d": 15
|
|
402
404
|
},
|
|
403
405
|
"schema_version": "2.0"
|
|
404
406
|
},
|
|
405
407
|
"restore-incident": {
|
|
406
408
|
"band": "Experimental",
|
|
407
|
-
"computed_at": "2026-05-
|
|
409
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
408
410
|
"evidence": {
|
|
409
411
|
"breaking_change_age_days": null,
|
|
410
|
-
"closed_tickets_window":
|
|
411
|
-
"days_shipped":
|
|
412
|
+
"closed_tickets_window": 99,
|
|
413
|
+
"days_shipped": 33,
|
|
412
414
|
"invocations_30d": 4
|
|
413
415
|
},
|
|
414
416
|
"schema_version": "2.0"
|
|
415
417
|
},
|
|
416
418
|
"review-problems": {
|
|
417
419
|
"band": "Experimental",
|
|
418
|
-
"computed_at": "2026-05-
|
|
420
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
419
421
|
"evidence": {
|
|
420
422
|
"breaking_change_age_days": null,
|
|
421
|
-
"closed_tickets_window":
|
|
422
|
-
"days_shipped":
|
|
423
|
+
"closed_tickets_window": 99,
|
|
424
|
+
"days_shipped": 33,
|
|
423
425
|
"invocations_30d": 9
|
|
424
426
|
},
|
|
425
427
|
"schema_version": "2.0"
|
|
426
428
|
},
|
|
427
429
|
"scaffold-intake": {
|
|
428
430
|
"band": "Experimental",
|
|
429
|
-
"computed_at": "2026-05-
|
|
431
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
430
432
|
"evidence": {
|
|
431
433
|
"breaking_change_age_days": null,
|
|
432
|
-
"closed_tickets_window":
|
|
433
|
-
"days_shipped":
|
|
434
|
+
"closed_tickets_window": 99,
|
|
435
|
+
"days_shipped": 33,
|
|
434
436
|
"invocations_30d": 1
|
|
435
437
|
},
|
|
436
438
|
"schema_version": "2.0"
|
|
437
439
|
},
|
|
438
440
|
"transition-problem": {
|
|
439
441
|
"band": "Experimental",
|
|
440
|
-
"computed_at": "2026-05-
|
|
442
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
441
443
|
"evidence": {
|
|
442
444
|
"breaking_change_age_days": null,
|
|
443
|
-
"closed_tickets_window":
|
|
444
|
-
"days_shipped":
|
|
445
|
-
"invocations_30d":
|
|
445
|
+
"closed_tickets_window": 99,
|
|
446
|
+
"days_shipped": 33,
|
|
447
|
+
"invocations_30d": 28
|
|
446
448
|
},
|
|
447
449
|
"schema_version": "2.0"
|
|
448
450
|
},
|
|
449
451
|
"transition-problems": {
|
|
450
452
|
"band": "Experimental",
|
|
451
|
-
"computed_at": "2026-05-
|
|
453
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
452
454
|
"evidence": {
|
|
453
455
|
"breaking_change_age_days": null,
|
|
454
|
-
"closed_tickets_window":
|
|
455
|
-
"days_shipped":
|
|
456
|
+
"closed_tickets_window": 99,
|
|
457
|
+
"days_shipped": 33,
|
|
456
458
|
"invocations_30d": 6
|
|
457
459
|
},
|
|
458
460
|
"schema_version": "2.0"
|
|
459
461
|
},
|
|
460
462
|
"work-problem": {
|
|
461
463
|
"band": "Experimental",
|
|
462
|
-
"computed_at": "2026-05-
|
|
464
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
463
465
|
"evidence": {
|
|
464
466
|
"breaking_change_age_days": null,
|
|
465
|
-
"closed_tickets_window":
|
|
466
|
-
"days_shipped":
|
|
467
|
+
"closed_tickets_window": 99,
|
|
468
|
+
"days_shipped": 33,
|
|
467
469
|
"invocations_30d": 2
|
|
468
470
|
},
|
|
469
471
|
"schema_version": "2.0"
|
|
470
472
|
},
|
|
471
473
|
"work-problems": {
|
|
472
474
|
"band": "Experimental",
|
|
473
|
-
"computed_at": "2026-05-
|
|
475
|
+
"computed_at": "2026-05-18T11:42:50Z",
|
|
474
476
|
"evidence": {
|
|
475
477
|
"breaking_change_age_days": null,
|
|
476
|
-
"closed_tickets_window":
|
|
477
|
-
"days_shipped":
|
|
478
|
+
"closed_tickets_window": 99,
|
|
479
|
+
"days_shipped": 33,
|
|
478
480
|
"invocations_30d": 6
|
|
479
481
|
},
|
|
480
482
|
"schema_version": "2.0"
|
|
@@ -482,5 +484,5 @@
|
|
|
482
484
|
}
|
|
483
485
|
},
|
|
484
486
|
"name": "wr-itil",
|
|
485
|
-
"version": "0.35.
|
|
487
|
+
"version": "0.35.4"
|
|
486
488
|
}
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @windyroad/itil
|
|
2
2
|
|
|
3
|
-
**ITIL-aligned IT service management for Claude Code.** Track recurring incidents, perform root cause analysis, and prioritise fixes using WSJF -- all inside your coding sessions. *Maturity: Experimental.*
|
|
3
|
+
**ITIL-aligned IT service management for Claude Code.** Track recurring incidents, perform root cause analysis, and prioritise fixes using WSJF -- all inside your coding sessions. *Maturity: Experimental (suite-bootstrap window; 327 invocations / 30d).*
|
|
4
4
|
|
|
5
5
|
Part of [Windy Road Agent Plugins](../../README.md).
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -418,6 +418,12 @@ for pkg_dir in plugin_dirs:
|
|
|
418
418
|
# NOT additive per ADR-058 §Confirmation #8.
|
|
419
419
|
kind_to_key = {"skill": "skills", "agent": "agents", "hook": "hooks", "command": "commands"}
|
|
420
420
|
surface_bands_for_rollup = []
|
|
421
|
+
# P269: collect per-surface invocations_30d across the populate pass so
|
|
422
|
+
# the rollup can carry the sum. Non-null integers participate in the sum;
|
|
423
|
+
# nulls (hook sentinel — architect §C) are excluded. All-null surface
|
|
424
|
+
# set yields a null rollup_invocations_30d to preserve the "not
|
|
425
|
+
# measurable" vs "measurably zero" honesty contract.
|
|
426
|
+
surface_invocations_for_rollup = []
|
|
421
427
|
|
|
422
428
|
# Pre-read existing nested maturity payload so re-runs preserve any
|
|
423
429
|
# forward-compat extras (architect issue 2: read-side line 417 fix).
|
|
@@ -450,6 +456,8 @@ for pkg_dir in plugin_dirs:
|
|
|
450
456
|
maturity_record["schema_version"] = "2.0"
|
|
451
457
|
new_map[name] = maturity_record
|
|
452
458
|
surface_bands_for_rollup.append(maturity_record.get("band"))
|
|
459
|
+
rec_inv = maturity_record.get("evidence", {}).get("invocations_30d")
|
|
460
|
+
surface_invocations_for_rollup.append(rec_inv)
|
|
453
461
|
new_maturity_kinds[key] = new_map
|
|
454
462
|
wrote_records += len(new_map)
|
|
455
463
|
|
|
@@ -458,9 +466,31 @@ for pkg_dir in plugin_dirs:
|
|
|
458
466
|
# at top level. Write-ordering fix (architect issue 2 line 441): build
|
|
459
467
|
# the entire `maturity:` dict in a single assignment so the rollup
|
|
460
468
|
# write does not clobber the per-kind nested maps.
|
|
469
|
+
#
|
|
470
|
+
# ADR-063 Amendment 2026-05-18 (P269 — rollup compound-evidence write):
|
|
471
|
+
# rollup additionally carries `rollup_invocations_30d` + `bootstrapping`
|
|
472
|
+
# so the Phase 3b renderer's AND-gated compound predicate
|
|
473
|
+
# (plugin-maturity-render.sh:146) can fire the
|
|
474
|
+
# `*Maturity: <Band> (suite-bootstrap window; <N> invocations / 30d).*`
|
|
475
|
+
# form during the bootstrapping window. Without these two fields the
|
|
476
|
+
# renderer falls through to bare-band, violating ADR-053 §Bootstrapping
|
|
477
|
+
# clause Phase 3 rendering requirement (line 88). Additive-within-2.0
|
|
478
|
+
# per ADR-058 §Confirmation #8 — old consumers reading
|
|
479
|
+
# `{schema_version, band}` continue to work; new consumers get the
|
|
480
|
+
# additional fields where present.
|
|
461
481
|
rollup = rollup_band(surface_bands_for_rollup)
|
|
462
482
|
if rollup is not None:
|
|
463
|
-
|
|
483
|
+
non_null_invs = [v for v in surface_invocations_for_rollup if isinstance(v, int)]
|
|
484
|
+
if non_null_invs:
|
|
485
|
+
rollup_invocations_30d = sum(non_null_invs)
|
|
486
|
+
else:
|
|
487
|
+
rollup_invocations_30d = None
|
|
488
|
+
maturity_doc = {
|
|
489
|
+
"schema_version": "2.0",
|
|
490
|
+
"band": rollup,
|
|
491
|
+
"rollup_invocations_30d": rollup_invocations_30d,
|
|
492
|
+
"bootstrapping": bootstrapping_active,
|
|
493
|
+
}
|
|
464
494
|
maturity_doc.update(new_maturity_kinds)
|
|
465
495
|
plugin_doc["maturity"] = maturity_doc
|
|
466
496
|
else:
|
|
@@ -173,6 +173,60 @@ PYEOF
|
|
|
173
173
|
done
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
# ── P269 — rollup compound-evidence fields shape (when present) ─────────────
|
|
177
|
+
|
|
178
|
+
@test "plugin-maturity-doc-lint: rollup rollup_invocations_30d is int or null (when present)" {
|
|
179
|
+
# ADR-063 §Amendment 2026-05-18 (P269 — rollup compound-evidence write):
|
|
180
|
+
# the rollup carries `rollup_invocations_30d: integer | null`. Integer when
|
|
181
|
+
# at least one per-surface entry has a non-null invocations_30d; null when
|
|
182
|
+
# ALL per-surface entries are null (e.g. hook-only plugins) — preserves the
|
|
183
|
+
# "not measurable" vs "measurably zero" honesty contract per architect §C.
|
|
184
|
+
# Per ADR-063 §Confirmation #10 (shape-when-present), this lint asserts
|
|
185
|
+
# type-shape when the field is present and tolerates absence for plugins
|
|
186
|
+
# that haven't been re-populated since the P269 amendment.
|
|
187
|
+
local plugin
|
|
188
|
+
for plugin in $(plugins_with_maturity); do
|
|
189
|
+
local pj="$REPO_ROOT/packages/$plugin/.claude-plugin/plugin.json"
|
|
190
|
+
python3 <<PYEOF
|
|
191
|
+
import json, sys
|
|
192
|
+
d = json.load(open("$pj"))
|
|
193
|
+
m = d["maturity"]
|
|
194
|
+
if "rollup_invocations_30d" not in m:
|
|
195
|
+
sys.exit(0) # field absent — tolerated per shape-when-present
|
|
196
|
+
v = m["rollup_invocations_30d"]
|
|
197
|
+
if v is None:
|
|
198
|
+
sys.exit(0)
|
|
199
|
+
if not isinstance(v, int) or isinstance(v, bool):
|
|
200
|
+
sys.exit(f"$plugin: maturity.rollup_invocations_30d = {v!r} ({type(v).__name__}); must be int or null")
|
|
201
|
+
if v < 0:
|
|
202
|
+
sys.exit(f"$plugin: maturity.rollup_invocations_30d = {v!r}; must be non-negative")
|
|
203
|
+
PYEOF
|
|
204
|
+
done
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@test "plugin-maturity-doc-lint: rollup bootstrapping is bool (when present)" {
|
|
208
|
+
# ADR-063 §Amendment 2026-05-18 (P269 — rollup compound-evidence write):
|
|
209
|
+
# the rollup carries `bootstrapping: bool` — populate-time snapshot of the
|
|
210
|
+
# bootstrapping-window state. The renderer's AND-gated compound predicate
|
|
211
|
+
# (plugin-maturity-render.sh:146) reads this flag to decide whether to
|
|
212
|
+
# emit the compound form. Shape-when-present per the same tolerance as
|
|
213
|
+
# rollup_invocations_30d above.
|
|
214
|
+
local plugin
|
|
215
|
+
for plugin in $(plugins_with_maturity); do
|
|
216
|
+
local pj="$REPO_ROOT/packages/$plugin/.claude-plugin/plugin.json"
|
|
217
|
+
python3 <<PYEOF
|
|
218
|
+
import json, sys
|
|
219
|
+
d = json.load(open("$pj"))
|
|
220
|
+
m = d["maturity"]
|
|
221
|
+
if "bootstrapping" not in m:
|
|
222
|
+
sys.exit(0)
|
|
223
|
+
v = m["bootstrapping"]
|
|
224
|
+
if not isinstance(v, bool):
|
|
225
|
+
sys.exit(f"$plugin: maturity.bootstrapping = {v!r} ({type(v).__name__}); must be bool")
|
|
226
|
+
PYEOF
|
|
227
|
+
done
|
|
228
|
+
}
|
|
229
|
+
|
|
176
230
|
# ── Regression fence (architect adjustment A1, iter-11): no top-level kind maps ─
|
|
177
231
|
|
|
178
232
|
@test "plugin-maturity-doc-lint: no top-level skills/agents/hooks/commands maturity-shaped records (iter-10 P0 hotfix fence)" {
|
|
@@ -343,9 +397,15 @@ PYEOF
|
|
|
343
397
|
[ -f "$rdm" ] || continue # README absent — skip (no marker to check)
|
|
344
398
|
local band
|
|
345
399
|
band=$(python3 -c "import json; print(json.load(open('$pj'))['maturity']['band'])")
|
|
346
|
-
# Anchored regex: `*Maturity: <band>` followed by `.` OR
|
|
347
|
-
|
|
348
|
-
|
|
400
|
+
# Anchored regex: `*Maturity: <band>` followed by `.` (bare form) OR
|
|
401
|
+
# ` (` (compound prefix — space + open paren per the renderer's
|
|
402
|
+
# `*Maturity: <Band> (suite-bootstrap window; <N> invocations / 30d).*`
|
|
403
|
+
# output shape at plugin-maturity-render.sh line 147). P269 fold-fix:
|
|
404
|
+
# the previous `[.(]` character class missed the space-before-paren
|
|
405
|
+
# case that became visible across the live monorepo once compound
|
|
406
|
+
# rendering started firing post-rollout.
|
|
407
|
+
if ! grep -qE "\\*Maturity: ${band}(\\.| \\()" "$rdm"; then
|
|
408
|
+
echo "$plugin: README missing badge marker *Maturity: ${band}<.|space-paren>" >&2
|
|
349
409
|
false
|
|
350
410
|
fi
|
|
351
411
|
done
|
|
@@ -298,7 +298,12 @@ print(obj if not isinstance(obj, (dict, list)) else json.dumps(obj))
|
|
|
298
298
|
[ "$(get_json_field "$pj" "maturity.skills.manage-problem.evidence.closed_tickets_window")" = "5" ]
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
-
@test "plugin-maturity-populate: plugin root rollup carries schema_version + band
|
|
301
|
+
@test "plugin-maturity-populate: plugin root rollup carries schema_version + band + rollup_invocations_30d + bootstrapping, no evidence" {
|
|
302
|
+
# P269 amendment: rollup now carries rollup_invocations_30d (sum of non-null
|
|
303
|
+
# per-surface invocations_30d) + bootstrapping (snapshot of window state at
|
|
304
|
+
# populate time) so the renderer's AND-gated compound predicate
|
|
305
|
+
# (plugin-maturity-render.sh:146) can fire. The §evidence dict is still NOT
|
|
306
|
+
# written on the rollup — only at per-surface entries.
|
|
302
307
|
make_plugin "rollupp" "skill:s1" "skill:s2"
|
|
303
308
|
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
304
309
|
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
@@ -318,6 +323,141 @@ print(obj if not isinstance(obj, (dict, list)) else json.dumps(obj))
|
|
|
318
323
|
[ "$(get_json_field "$pj" "maturity.schema_version")" = "2.0" ]
|
|
319
324
|
[ "$(get_json_field "$pj" "maturity.band")" != "MISSING" ]
|
|
320
325
|
[ "$(get_json_field "$pj" "maturity.evidence")" = "MISSING" ]
|
|
326
|
+
[ "$(get_json_field "$pj" "maturity.rollup_invocations_30d")" != "MISSING" ]
|
|
327
|
+
[ "$(get_json_field "$pj" "maturity.bootstrapping")" != "MISSING" ]
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
# ── P269: rollup_invocations_30d sums non-null per-surface entries ───────────
|
|
331
|
+
|
|
332
|
+
@test "plugin-maturity-populate: rollup_invocations_30d equals sum of non-null per-surface invocations" {
|
|
333
|
+
# P269 fix details step 1: rollup_invocations_30d = sum across non-null
|
|
334
|
+
# per-surface entries. 200 + 1 = 201.
|
|
335
|
+
make_plugin "summp" "skill:s1" "skill:s2"
|
|
336
|
+
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
337
|
+
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
338
|
+
write_transcript_ndjson "$trans" \
|
|
339
|
+
"skill" "wr-summp:s1" 200 \
|
|
340
|
+
"skill" "wr-summp:s2" 1
|
|
341
|
+
write_exercise_ndjson "$exer" "summp" 10 20 2 NULL
|
|
342
|
+
|
|
343
|
+
run "$SCRIPT" \
|
|
344
|
+
--transcript-ndjson="$trans" \
|
|
345
|
+
--exercise-ndjson="$exer" \
|
|
346
|
+
--project-root="$PROJECT_ROOT" \
|
|
347
|
+
--now=2026-05-17T12:00:00Z
|
|
348
|
+
[ "$status" -eq 0 ]
|
|
349
|
+
|
|
350
|
+
local pj="$PROJECT_ROOT/packages/summp/.claude-plugin/plugin.json"
|
|
351
|
+
[ "$(get_json_field "$pj" "maturity.rollup_invocations_30d")" = "201" ]
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
# ── P269: rollup_invocations_30d sums non-null only (hooks excluded) ────────
|
|
355
|
+
|
|
356
|
+
@test "plugin-maturity-populate: rollup_invocations_30d excludes null hook surfaces from sum" {
|
|
357
|
+
# Mixed surfaces — a skill with invocations + a hook with null sentinel.
|
|
358
|
+
# The sum should equal the skill invocations alone; the null hook does NOT
|
|
359
|
+
# participate in the sum (architect §C null sentinel preserves
|
|
360
|
+
# "not measurable" vs "measurably zero" semantics).
|
|
361
|
+
make_plugin "mixp" "skill:thing" "hook:somehook"
|
|
362
|
+
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
363
|
+
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
364
|
+
write_transcript_ndjson "$trans" "skill" "wr-mixp:thing" 75
|
|
365
|
+
write_exercise_ndjson "$exer" "mixp" 10 20 2 NULL
|
|
366
|
+
|
|
367
|
+
run "$SCRIPT" \
|
|
368
|
+
--transcript-ndjson="$trans" \
|
|
369
|
+
--exercise-ndjson="$exer" \
|
|
370
|
+
--project-root="$PROJECT_ROOT" \
|
|
371
|
+
--now=2026-05-17T12:00:00Z
|
|
372
|
+
[ "$status" -eq 0 ]
|
|
373
|
+
|
|
374
|
+
local pj="$PROJECT_ROOT/packages/mixp/.claude-plugin/plugin.json"
|
|
375
|
+
[ "$(get_json_field "$pj" "maturity.rollup_invocations_30d")" = "75" ]
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
# ── P269: rollup_invocations_30d is null when ALL per-surface entries are null ─
|
|
379
|
+
|
|
380
|
+
@test "plugin-maturity-populate: rollup_invocations_30d is null on hook-only plugin" {
|
|
381
|
+
# Hook-only plugin: every per-surface invocations_30d is null. The rollup
|
|
382
|
+
# MUST emit null (not 0) so the renderer's AND-gated compound predicate
|
|
383
|
+
# falls through correctly — `0 invocations / 30d` would lie.
|
|
384
|
+
make_plugin "hookonly" "hook:a" "hook:b"
|
|
385
|
+
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
386
|
+
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
387
|
+
: >"$trans" # empty transcript — hooks never appear there
|
|
388
|
+
write_exercise_ndjson "$exer" "hookonly" 5 30 1 NULL
|
|
389
|
+
|
|
390
|
+
run "$SCRIPT" \
|
|
391
|
+
--transcript-ndjson="$trans" \
|
|
392
|
+
--exercise-ndjson="$exer" \
|
|
393
|
+
--project-root="$PROJECT_ROOT" \
|
|
394
|
+
--now=2026-05-17T12:00:00Z
|
|
395
|
+
[ "$status" -eq 0 ]
|
|
396
|
+
|
|
397
|
+
local pj="$PROJECT_ROOT/packages/hookonly/.claude-plugin/plugin.json"
|
|
398
|
+
# `get_json_field` collapses null to display "None"; check the raw JSON.
|
|
399
|
+
local raw
|
|
400
|
+
raw=$(python3 -c "
|
|
401
|
+
import json
|
|
402
|
+
obj = json.load(open('$pj'))
|
|
403
|
+
print(json.dumps(obj['maturity']['rollup_invocations_30d']))
|
|
404
|
+
")
|
|
405
|
+
[ "$raw" = "null" ]
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
# ── P269: bootstrapping flag write — true during bootstrapping window ───────
|
|
409
|
+
|
|
410
|
+
@test "plugin-maturity-populate: rollup bootstrapping=true during bootstrapping window" {
|
|
411
|
+
# suite_oldest_days < 60 → bootstrapping active → rollup carries true.
|
|
412
|
+
make_plugin "bsp" "skill:s1"
|
|
413
|
+
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
414
|
+
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
415
|
+
write_transcript_ndjson "$trans" "skill" "wr-bsp:s1" 50
|
|
416
|
+
write_exercise_ndjson "$exer" "bsp" 10 20 2 NULL # days_shipped=20 < 60
|
|
417
|
+
|
|
418
|
+
run "$SCRIPT" \
|
|
419
|
+
--transcript-ndjson="$trans" \
|
|
420
|
+
--exercise-ndjson="$exer" \
|
|
421
|
+
--project-root="$PROJECT_ROOT" \
|
|
422
|
+
--now=2026-05-17T12:00:00Z
|
|
423
|
+
[ "$status" -eq 0 ]
|
|
424
|
+
|
|
425
|
+
local pj="$PROJECT_ROOT/packages/bsp/.claude-plugin/plugin.json"
|
|
426
|
+
local raw
|
|
427
|
+
raw=$(python3 -c "
|
|
428
|
+
import json
|
|
429
|
+
obj = json.load(open('$pj'))
|
|
430
|
+
print(json.dumps(obj['maturity']['bootstrapping']))
|
|
431
|
+
")
|
|
432
|
+
[ "$raw" = "true" ]
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
# ── P269: bootstrapping flag write — false once max(days_shipped) ≥ 60 ──────
|
|
436
|
+
|
|
437
|
+
@test "plugin-maturity-populate: rollup bootstrapping=false once suite_oldest_days >= 60" {
|
|
438
|
+
# max(days_shipped) >= 60 → bootstrapping inactive → rollup carries false.
|
|
439
|
+
# Independent of --now (auto-derives from data per architect §D).
|
|
440
|
+
make_plugin "stp" "skill:s1"
|
|
441
|
+
local trans="$FIXTURE_DIR/transcript.ndjson"
|
|
442
|
+
local exer="$FIXTURE_DIR/exercise.ndjson"
|
|
443
|
+
write_transcript_ndjson "$trans" "skill" "wr-stp:s1" 50
|
|
444
|
+
write_exercise_ndjson "$exer" "stp" 100 200 15 NULL # days_shipped=200 >= 60
|
|
445
|
+
|
|
446
|
+
run "$SCRIPT" \
|
|
447
|
+
--transcript-ndjson="$trans" \
|
|
448
|
+
--exercise-ndjson="$exer" \
|
|
449
|
+
--project-root="$PROJECT_ROOT" \
|
|
450
|
+
--now=2026-05-17T12:00:00Z
|
|
451
|
+
[ "$status" -eq 0 ]
|
|
452
|
+
|
|
453
|
+
local pj="$PROJECT_ROOT/packages/stp/.claude-plugin/plugin.json"
|
|
454
|
+
local raw
|
|
455
|
+
raw=$(python3 -c "
|
|
456
|
+
import json
|
|
457
|
+
obj = json.load(open('$pj'))
|
|
458
|
+
print(json.dumps(obj['maturity']['bootstrapping']))
|
|
459
|
+
")
|
|
460
|
+
[ "$raw" = "false" ]
|
|
321
461
|
}
|
|
322
462
|
|
|
323
463
|
# ── Granularity contract (ADR-063 #10): rollup = worst-case among surfaces ──
|
|
@@ -151,6 +151,64 @@ make_plugin() {
|
|
|
151
151
|
[[ "$out" != *"invocations"* ]]
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
# ── P269: AND-gated compound predicate — null rollup_invocations_30d → bare ─
|
|
155
|
+
|
|
156
|
+
@test "rollup badge: bootstrapping=true + rollup_invocations_30d=null → bare-band (hook-only plugin)" {
|
|
157
|
+
# P269: when populate writes bootstrapping=true but rollup_invocations_30d
|
|
158
|
+
# is null (hook-only plugin — no countable surfaces), the renderer's
|
|
159
|
+
# AND-gated compound predicate at plugin-maturity-render.sh:146 must fall
|
|
160
|
+
# through to bare-band. `0 invocations / 30d` would lie; bare-band is the
|
|
161
|
+
# honest fall-through.
|
|
162
|
+
make_plugin "hookonly" '{"name":"wr-hookonly","version":"0.1.0","description":"Hook-only","maturity":{"schema_version":"2.0","band":"Experimental","bootstrapping":true,"rollup_invocations_30d":null}}' \
|
|
163
|
+
"# @windyroad/hookonly
|
|
164
|
+
|
|
165
|
+
**Hook-only plugin description.**
|
|
166
|
+
|
|
167
|
+
## Skills
|
|
168
|
+
|
|
169
|
+
| Skill | Purpose |
|
|
170
|
+
|-------|---------|
|
|
171
|
+
| /wr-hookonly:thing | Does a thing |
|
|
172
|
+
"
|
|
173
|
+
|
|
174
|
+
run bash "$SCRIPT" --project-root="$PROJECT_ROOT"
|
|
175
|
+
[ "$status" -eq 0 ]
|
|
176
|
+
|
|
177
|
+
local out; out="$(cat "$PROJECT_ROOT/packages/hookonly/README.md")"
|
|
178
|
+
[[ "$out" == *"*Maturity: Experimental.*"* ]]
|
|
179
|
+
[[ "$out" != *"suite-bootstrap"* ]]
|
|
180
|
+
[[ "$out" != *"invocations"* ]]
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
# ── P269: AND-gated compound predicate — bootstrapping=false → bare-band ────
|
|
184
|
+
|
|
185
|
+
@test "rollup badge: bootstrapping=false + rollup_invocations_30d=integer → bare-band (post-sunset)" {
|
|
186
|
+
# P269: when bootstrapping has lapsed (suite_oldest_days >= 60), populate
|
|
187
|
+
# writes bootstrapping=false. Even with a non-null rollup_invocations_30d,
|
|
188
|
+
# the AND-gated predicate falls through to bare-band — the compound
|
|
189
|
+
# rendering is scoped to the bootstrapping window per ADR-053 §Bootstrapping
|
|
190
|
+
# clause Phase 3 rendering requirement.
|
|
191
|
+
make_plugin "stedp" '{"name":"wr-stedp","version":"0.1.0","description":"Steady","maturity":{"schema_version":"2.0","band":"Beta","bootstrapping":false,"rollup_invocations_30d":1500}}' \
|
|
192
|
+
"# @windyroad/stedp
|
|
193
|
+
|
|
194
|
+
**Steady-state plugin description.**
|
|
195
|
+
|
|
196
|
+
## Skills
|
|
197
|
+
|
|
198
|
+
| Skill | Purpose |
|
|
199
|
+
|-------|---------|
|
|
200
|
+
| /wr-stedp:thing | Does a thing |
|
|
201
|
+
"
|
|
202
|
+
|
|
203
|
+
run bash "$SCRIPT" --project-root="$PROJECT_ROOT"
|
|
204
|
+
[ "$status" -eq 0 ]
|
|
205
|
+
|
|
206
|
+
local out; out="$(cat "$PROJECT_ROOT/packages/stedp/README.md")"
|
|
207
|
+
[[ "$out" == *"*Maturity: Beta.*"* ]]
|
|
208
|
+
[[ "$out" != *"suite-bootstrap"* ]]
|
|
209
|
+
[[ "$out" != *"invocations"* ]]
|
|
210
|
+
}
|
|
211
|
+
|
|
154
212
|
# ── Confirmation #2 (ADR-063): per-skill Maturity column populated ──────────
|
|
155
213
|
|
|
156
214
|
@test "per-skill column: adds Maturity column to existing Skills table" {
|