@windyroad/itil 0.51.0 → 0.51.1
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/package.json
CHANGED
|
@@ -853,9 +853,9 @@ After the rename + README refresh land but BEFORE the Step 11 commit, fire the b
|
|
|
853
853
|
|
|
854
854
|
This subsection is the **copy-not-move sibling** of `transition-problem` SKILL.md Step 7b per [ADR-010](../../../docs/decisions/010-rename-wr-problem-to-wr-itil.proposed.md) amended "Split-skill execution ownership" rule (P093). The user-initiated transition path lives in `/wr-itil:transition-problem`; the in-skill callers (Step 9b auto-transition, Step 9d closure inside review, the Parked path) need the same lifecycle-update trigger and carry their own scoped copy. Drift between the two copies re-opens P080's bidirectional gap on the in-skill paths.
|
|
855
855
|
|
|
856
|
-
The trigger fires **whenever the ticket carries a `## Reported Upstream` section** — gate the Skill-tool dispatch behind a one-line mechanical pre-check rather than dispatching on every transition. Dispatching unconditionally pays the full `/wr-itil:update-upstream` SKILL.md context load (~14 KB into the calling agent's context) just to hit the sibling skill's no-op exit; the common case is a ticket with
|
|
856
|
+
The trigger fires **whenever the ticket carries a `## Reported Upstream` section (outbound) OR an `**Origin**: inbound-reported (#NN)` field (inbound, P363)** — gate the Skill-tool dispatch behind a one-line mechanical pre-check rather than dispatching on every transition. Dispatching unconditionally pays the full `/wr-itil:update-upstream` SKILL.md context load (~14 KB into the calling agent's context) just to hit the sibling skill's no-op exit; the common case is a ticket with neither surface, so the load is wasted (P362). The grep IS the trigger: it preserves the fire-whenever-a-surface-exists semantics — an upstream/inbound comment posts iff one of the two surfaces is present — while eliminating the context load for the common no-op case. Authority: [ADR-054](../../../docs/decisions/054-skill-md-runtime-budget-policy.proposed.md) (SKILL.md runtime-budget policy; [ADR-038](../../../docs/decisions/038-progressive-disclosure-for-governance-tooling-context.proposed.md) progressive-disclosure as the ancestor principle); [ADR-024](../../../docs/decisions/024-cross-project-problem-reporting-contract.proposed.md) amendment (P363) for the inbound-origin alternation.
|
|
857
857
|
|
|
858
|
-
**Pre-check first** (mechanical — no user decision): run `grep -
|
|
858
|
+
**Pre-check first** (mechanical — no user decision): run `grep -qE '^## Reported Upstream|^\*\*Origin\*\*: inbound-reported \(#' <ticket-file>`. If it does NOT match (NEITHER the outbound `## Reported Upstream` section NOR the inbound `**Origin**: inbound-reported (#NN)` field is present), skip the Skill dispatch entirely, log one line (`no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update`), and proceed to Step 11. Only when it matches, invoke the sibling skill via the Skill tool:
|
|
859
859
|
|
|
860
860
|
```
|
|
861
861
|
/wr-itil:update-upstream <NNN>
|
|
@@ -863,7 +863,8 @@ The trigger fires **whenever the ticket carries a `## Reported Upstream` section
|
|
|
863
863
|
|
|
864
864
|
Behaviour matrix:
|
|
865
865
|
|
|
866
|
-
- **
|
|
866
|
+
- **Neither `## Reported Upstream` section nor inbound `**Origin**` field on the local ticket** → the grep pre-check skips the Skill dispatch (no context load); log `no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update` and proceed to Step 11. (The sibling skill retains its own Step 1 no-op exit as defence-in-depth for any path that reaches it directly.)
|
|
867
|
+
- **`**Origin**: inbound-reported (#NN)` present** → the sibling skill runs its inbound-origin verdict dispatch leg (P363): posts the reporter-facing fix-released / closed verdict on the originating own-repo issue through the same external-comms + voice-tone gates, idempotency-guarded, and back-writes a direction-tagged `## Upstream Lifecycle Updates` entry. If BOTH surfaces are present, the outbound and inbound legs fire independently.
|
|
867
868
|
- **`## Reported Upstream` present AND both gates within appetite** → the sibling skill posts via `gh issue comment` (and on Verifying → Closed, also `gh issue close`), back-writes to `## Upstream Lifecycle Updates`, and stages the back-write into the index. The Step 11 commit captures the back-write alongside the transition.
|
|
868
869
|
- **`## Reported Upstream` present AND above-appetite (after silent risk-reduce + re-score)** → the sibling skill saves the drafted comment to `## Queued Upstream Update` and queues an `outstanding_questions` entry. The Step 11 commit captures the `## Queued Upstream Update` appendage alongside the transition. **The orchestrator continues per P352 queue-and-continue** — do NOT halt the transition on an above-appetite upstream update.
|
|
869
870
|
|
|
@@ -260,9 +260,9 @@ The refresh uses the same rendering rules as `/wr-itil:review-problems` Step 9e
|
|
|
260
260
|
|
|
261
261
|
After the rename + README refresh land but BEFORE the Step 8 commit, fire the bidirectional lifecycle-update sibling skill so the upstream issue (if any) receives the lifecycle update comment in the SAME commit as the transition per ADR-014 single-commit grain. This is the **outbound-lifecycle-update leg** of the reporter loop (the inbound-discovery leg is owned by ADR-062's assessment pipeline; together they close the reporter relationship per JTBD-301 + JTBD-201).
|
|
262
262
|
|
|
263
|
-
The trigger fires **whenever the ticket carries a `## Reported Upstream` section** — gate the Skill-tool dispatch behind a one-line mechanical pre-check rather than dispatching on every transition. Dispatching unconditionally pays the full `/wr-itil:update-upstream` SKILL.md context load (~14 KB into the calling agent's context) just to hit the sibling skill's no-op exit; the common case is a ticket with
|
|
263
|
+
The trigger fires **whenever the ticket carries a `## Reported Upstream` section (outbound) OR an `**Origin**: inbound-reported (#NN)` field (inbound, P363)** — gate the Skill-tool dispatch behind a one-line mechanical pre-check rather than dispatching on every transition. Dispatching unconditionally pays the full `/wr-itil:update-upstream` SKILL.md context load (~14 KB into the calling agent's context) just to hit the sibling skill's no-op exit; the common case is a ticket with neither surface, so the load is wasted (P362). The grep IS the trigger: it preserves the fire-whenever-a-surface-exists semantics — an upstream/inbound comment posts iff one of the two surfaces is present — while eliminating the context load for the common no-op case. Authority: [ADR-054](../../../docs/decisions/054-skill-md-runtime-budget-policy.proposed.md) (SKILL.md runtime-budget policy; [ADR-038](../../../docs/decisions/038-progressive-disclosure-for-governance-tooling-context.proposed.md) progressive-disclosure as the ancestor principle); [ADR-024](../../../docs/decisions/024-cross-project-problem-reporting-contract.proposed.md) amendment (P363) for the inbound-origin alternation.
|
|
264
264
|
|
|
265
|
-
**Pre-check first** (mechanical — no user decision): run `grep -
|
|
265
|
+
**Pre-check first** (mechanical — no user decision): run `grep -qE '^## Reported Upstream|^\*\*Origin\*\*: inbound-reported \(#' <ticket-file>`. If it does NOT match (NEITHER the outbound `## Reported Upstream` section NOR the inbound `**Origin**: inbound-reported (#NN)` field is present), skip the Skill dispatch entirely, log one line (`no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update`), and proceed to Step 8. Only when it matches, invoke the sibling skill via the Skill tool:
|
|
266
266
|
|
|
267
267
|
```
|
|
268
268
|
/wr-itil:update-upstream <NNN>
|
|
@@ -270,7 +270,8 @@ The trigger fires **whenever the ticket carries a `## Reported Upstream` section
|
|
|
270
270
|
|
|
271
271
|
Behaviour matrix:
|
|
272
272
|
|
|
273
|
-
- **
|
|
273
|
+
- **Neither `## Reported Upstream` section nor inbound `**Origin**` field on the local ticket** → the grep pre-check skips the Skill dispatch (no context load); log `no ## Reported Upstream section and no inbound Origin; skipping upstream lifecycle update` and proceed to Step 8. (The sibling skill retains its own Step 1 no-op exit as defence-in-depth for any path that reaches it directly.)
|
|
274
|
+
- **`**Origin**: inbound-reported (#NN)` present** → the sibling skill runs its inbound-origin verdict dispatch leg (P363): posts the reporter-facing fix-released / closed verdict on the originating own-repo issue through the same external-comms + voice-tone gates, idempotency-guarded, and back-writes a direction-tagged `## Upstream Lifecycle Updates` entry. If BOTH surfaces are present, the outbound and inbound legs fire independently.
|
|
274
275
|
- **`## Reported Upstream` present AND both gates within appetite** → the sibling skill posts via `gh issue comment` (and on Verifying → Closed, also `gh issue close`), back-writes to `## Upstream Lifecycle Updates`, and stages the back-write into the index. The Step 8 commit captures the back-write alongside the transition.
|
|
275
276
|
- **`## Reported Upstream` present AND above-appetite (after silent risk-reduce + re-score)** → the sibling skill saves the drafted comment to `## Queued Upstream Update` and queues an `outstanding_questions` entry. The Step 8 commit captures the `## Queued Upstream Update` appendage alongside the transition. **The orchestrator continues per P352 queue-and-continue** — do NOT halt the transition on an above-appetite upstream update.
|
|
276
277
|
|
|
@@ -44,7 +44,8 @@ The single-ticket form is typically invoked from `/wr-itil:transition-problem` S
|
|
|
44
44
|
## Scope
|
|
45
45
|
|
|
46
46
|
**In scope:**
|
|
47
|
-
- Read the local ticket's `## Reported Upstream` section and extract each upstream URL + matched template + disclosure path recorded there.
|
|
47
|
+
- Read the local ticket's `## Reported Upstream` section and extract each upstream URL + matched template + disclosure path recorded there (**outbound** direction).
|
|
48
|
+
- Read the local ticket's `**Origin**: inbound-reported (#NN)` field and dispatch a reporter-facing fix-released / closed verdict comment on the originating own-repo issue (**inbound** direction, P363). See [§ Inbound-origin verdict dispatch (P363)](#inbound-origin-verdict-dispatch-p363).
|
|
48
49
|
- Determine the local ticket's current Status from the filename suffix.
|
|
49
50
|
- Draft a transition-specific lifecycle-update comment per the templates below (Open→KE / KE→Verifying / Verifying→Closed).
|
|
50
51
|
- Compose the drafted prose through `wr-risk-scorer:external-comms` + `wr-voice-tone:external-comms` gates.
|
|
@@ -87,11 +88,12 @@ LOCAL_TICKET=$(ls docs/problems/${LOCAL_ID}-*.{open,known-error,verifying,closed
|
|
|
87
88
|
Extract:
|
|
88
89
|
- Title (from H1).
|
|
89
90
|
- Current Status (from filename suffix — `.open.md` / `.known-error.md` / `.verifying.md` / `.closed.md` / `.parked.md`).
|
|
90
|
-
- The `## Reported Upstream` section (zero or more upstream entries, each with URL + disclosure path).
|
|
91
|
+
- The `## Reported Upstream` section (zero or more **outbound** upstream entries, each with URL + disclosure path) — the **outbound** direction (a ticket *we* reported up to someone else).
|
|
92
|
+
- The `**Origin**: inbound-reported (#NN)` field (the [ADR-076](../../../docs/decisions/076-inbound-reported-problems-rank-ahead-via-sort-tier.proposed.md) rank-authoritative on-ticket field) — the **inbound** direction (a ticket someone else reported *against us* on our own repo, `#NN` being the originating issue). Drives the inbound dispatch leg below (P363).
|
|
91
93
|
- For `.verifying.md` tickets: the `## Fix Released` section (release marker, version, commit SHA, PR number).
|
|
92
94
|
- For `.known-error.md` tickets: the `## Fix Strategy` section (planned fix path; cited in KE updates so the reporter knows the direction).
|
|
93
95
|
|
|
94
|
-
If the ticket has
|
|
96
|
+
**No-op exit (dual-direction).** If the ticket has NEITHER a `## Reported Upstream` section NOR an `**Origin**: inbound-reported (#NN)` field, exit cleanly with a one-line message: `No ## Reported Upstream section and no inbound Origin in P${LOCAL_ID}; nothing to update.` This is the **no-op exit** — most local tickets are neither reported upstream nor inbound-originated, and the skill's invocation from `transition-problem` Step 7 is unconditional; a missing surface is the common case, not an error. When EITHER surface is present, proceed: the outbound entries route through Steps 2–6; the inbound Origin field routes through the [§ Inbound-origin verdict dispatch (P363)](#inbound-origin-verdict-dispatch-p363) leg below. When BOTH are present, the two legs fire **independently** (each gate-composed, posted, and logged separately).
|
|
95
97
|
|
|
96
98
|
### 2. Parse each upstream entry
|
|
97
99
|
|
|
@@ -286,6 +288,93 @@ Append a log entry to the local ticket's `## Upstream Lifecycle Updates` section
|
|
|
286
288
|
|
|
287
289
|
The log is append-only — each transition adds an entry; earlier entries are never overwritten. The log is the audit trail per JTBD-201's symmetric-audit-trail outcome and per ADR-024 Confirmation criterion 3a's `## Reported Upstream` back-write pattern (extended for the bidirectional case).
|
|
288
290
|
|
|
291
|
+
### Inbound-origin verdict dispatch (P363)
|
|
292
|
+
|
|
293
|
+
<!-- @jtbd JTBD-301 (Report a Problem Without Pre-Classifying It — inbound reporter feedback loop: the fix-released verdict leg for tickets someone else filed against us) -->
|
|
294
|
+
|
|
295
|
+
This leg runs **in addition to** Steps 2–6 (the outbound `## Reported Upstream` path), keyed off the `**Origin**: inbound-reported (#NN)` field Step 1 extracted. It closes the JTBD-301 fix-released-verdict promise for the **inbound** direction — a plugin-user filed a `problem-report` issue *against us* (recorded at intake by ADR-062's safe-and-valid branch, which stamps the on-ticket `**Origin**` field per [ADR-076](../../../docs/decisions/076-inbound-reported-problems-rank-ahead-via-sort-tier.proposed.md)) and never heard the fix shipped because the outbound machinery only reads `## Reported Upstream`. Authority: [ADR-024](../../../docs/decisions/024-cross-project-problem-reporting-contract.proposed.md) amendment (P363, inbound-verdict dispatch leg).
|
|
296
|
+
|
|
297
|
+
**Why the Origin field, not `## Reported Upstream` (P363 design):** the inbound issue lives on OUR OWN repo (it was filed against us). Writing it into `## Reported Upstream` would contaminate `/wr-itil:check-upstream-responses` (P249), which polls that section as OUTBOUND issues we filed *elsewhere*. Consuming the `**Origin**` field — distinct by construction — keeps the inbound and outbound data shapes separate and P249 uncontaminated.
|
|
298
|
+
|
|
299
|
+
#### I1. Parse the inbound origin
|
|
300
|
+
|
|
301
|
+
From the `**Origin**: inbound-reported (#NN)` field, extract the originating issue number `NN`. Resolve the repo it lives on as **our own repo** — the `gh` default for the current working tree (`gh repo view --json nameWithOwner -q .nameWithOwner`), NOT an external upstream owner/repo. If the `**Origin**` field is `internal` or absent, this leg does not run (the no-op is already handled at Step 1 when both surfaces are absent).
|
|
302
|
+
|
|
303
|
+
#### I2. Determine the transition (same suffix logic as Step 3)
|
|
304
|
+
|
|
305
|
+
Reuse Step 3's transition table (filename-suffix vs last-logged Status) — it is direction-agnostic. The inbound leg fires verdict comments for the **fix-released** and **closed** transitions (the verdicts a reporter most wants); Open → Known Error fires an optional progress comment only when the reporter explicitly asked for status. If the suffix matches the last logged inbound entry, exit no-op (`No inbound transition since last update; nothing to post.`).
|
|
306
|
+
|
|
307
|
+
#### I3. Draft the inbound verdict comment (reporter-facing)
|
|
308
|
+
|
|
309
|
+
Per-transition templates, filled from the local ticket per Step 1's extraction. **Anti-leakage (P229/P350) — load-bearing:** these bodies are reporter-facing on our own repo and MUST carry reporter-surface prose only. Do NOT emit framework-internal vocabulary — no Step IDs, branch names, classification tokens (`safe-and-valid`, `inbound-reported`, …), `P<NNN>` / `ADR-NNN` / `JTBD-NNN` / `RFC-NNN` as carriers of meaning, or `docs/problems/...` path syntax. The released `@windyroad/<pkg>@<version>` upgrade target is the only permitted structured token. This mirrors ADR-062's safe-and-valid acknowledgement shape (Decision Outcome step 6). The same **no-invention rule** as Step 4's outbound templates applies — if a cited section is absent, write the explicit "absent" phrasing, never synthesise technical claims.
|
|
310
|
+
|
|
311
|
+
**Known Error → Verification Pending (fix released) template:**
|
|
312
|
+
|
|
313
|
+
```markdown
|
|
314
|
+
Thanks again for the report. The fix has shipped in `@windyroad/<pkg>@<version>`.
|
|
315
|
+
|
|
316
|
+
**What changed**: <one-sentence reporter-readable summary from the ## Fix Released section>
|
|
317
|
+
|
|
318
|
+
Please upgrade to that version (or later) and let us know if you still see this. If anything looks off after upgrading, just reply here.
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Verification Pending → Closed template:**
|
|
322
|
+
|
|
323
|
+
```markdown
|
|
324
|
+
Closing the loop — this is fixed in `@windyroad/<pkg>@<version>` and we've confirmed it on our side. Thanks for taking the time to report it; your filing is what got it fixed. Reopen or reply here if it resurfaces.
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Open → Known Error (optional progress) template** (only when the reporter asked for interim status):
|
|
328
|
+
|
|
329
|
+
```markdown
|
|
330
|
+
Quick update: we've found the cause and a fix is on the way. We'll comment here again when it ships in a release.
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### I4. Idempotency guard (before posting)
|
|
334
|
+
|
|
335
|
+
Inbound dispatch may re-fire (re-run on a later transition, or a stale-grep re-dispatch). Before posting, scan the originating issue's existing comments:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
gh issue view "${NN}" --repo "${OWN_OWNER_REPO}" --json comments \
|
|
339
|
+
-q '.comments[].body' | grep -F "@windyroad/${PKG}@${VERSION}"
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
The verdict marker is the released `@windyroad/<pkg>@<version>` string (plus the commit SHA carried in `## Fix Released` when present) — unique enough that a prior matching comment means the verdict already posted. If a matching comment is found, **skip the post**, back-write an `already-posted-inbound` reconciliation entry to the lifecycle log (I6), and continue. This makes the inbound leg idempotent on re-runs.
|
|
343
|
+
|
|
344
|
+
#### I5. Compose through gates + post (same composition as Step 5)
|
|
345
|
+
|
|
346
|
+
Route the drafted comment through the SAME `wr-risk-scorer:external-comms` + `wr-voice-tone:external-comms` dual gate (AND composition) as Step 5 — no weaker path for inbound. Above-appetite handling is identical to Step 5c (silent risk-reduce + re-score; if still above, save to `## Queued Upstream Update` + queue an `outstanding_questions` entry; the orchestrator continues per P352 — do NOT halt). Within appetite, post on our own repo:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
gh issue comment "${NN}" --repo "${OWN_OWNER_REPO}" --body "${INBOUND_BODY}"
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
On the **Verification Pending → Closed** transition, after the comment, also close the originating issue so our own tracker matches the local `.closed.md` state (this addresses the P211 #97 *silent-and-unclosed* witness):
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
gh issue close "${NN}" --repo "${OWN_OWNER_REPO}" --comment "" --reason completed
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
If the issue is already closed (someone closed it manually), `gh issue close` returns a benign error — record `closed-already` in the disclosure path and continue.
|
|
359
|
+
|
|
360
|
+
#### I6. Back-write to the lifecycle log
|
|
361
|
+
|
|
362
|
+
Append to the same `## Upstream Lifecycle Updates` log (Step 6 shape), tagged for the inbound direction so the audit trail stays unified:
|
|
363
|
+
|
|
364
|
+
```markdown
|
|
365
|
+
- **<YYYY-MM-DD>** — Known Error → Verification Pending (inbound)
|
|
366
|
+
- **Target**: inbound #<NN> (own repo <OWN_OWNER_REPO>)
|
|
367
|
+
- **Comment URL**: <posted-comment-url> (or "skipped — already-posted-inbound" when the idempotency guard matched, or "queued — see ## Queued Upstream Update" when above-appetite)
|
|
368
|
+
- **Disclosure path**: posted-inbound-comment | posted-inbound-comment-and-closed (Verifying → Closed) | already-posted-inbound | queued-above-appetite | closed-already
|
|
369
|
+
- **Gate verdict**: external-comms <band/score> + voice-tone <pass|fail>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
The log stays append-only and direction-tagged; `/wr-itil:check-upstream-responses` (P249) does NOT read this section, so logging inbound entries here cannot contaminate the outbound poller.
|
|
373
|
+
|
|
374
|
+
#### I7. Both-direction tickets
|
|
375
|
+
|
|
376
|
+
A ticket may carry BOTH a `## Reported Upstream` section AND an inbound `**Origin**` field (we reported it upstream *and* someone reported it against us). The two legs are **independent**: the outbound entries run Steps 2–6 against their external URLs; the inbound leg runs I1–I6 against the own-repo issue. Each gate-composes, posts, and logs separately — one above-appetite leg queues only itself; the other proceeds.
|
|
377
|
+
|
|
289
378
|
### 7. Commit per ADR-014
|
|
290
379
|
|
|
291
380
|
When invoked from `transition-problem` Step 7's advisory subsection, the upstream comment + back-write + the ticket rename + the README refresh all join the **same single commit** per ADR-014's single-commit grain — never split across commits. The transition-problem skill owns the commit; this skill's edits ride that commit as additional staged changes.
|
|
@@ -359,6 +448,7 @@ Four distinct AFK branches. Per the [ADR-024](../../../docs/decisions/024-cross-
|
|
|
359
448
|
| Above-appetite — silent risk-reduce + re-score within appetite | Re-draft with tighter source-citation + shorter prose; re-invoke `wr-risk-scorer:external-comms`. If within → post per the below-appetite branch. | ADR-024 amendment (P080); ADR-044 framework-resolution boundary; ADR-042 within-axis precedent (open-vocabulary risk-reducing measures) |
|
|
360
449
|
| Above-appetite — silent risk-reduce did not bring within appetite | Save drafted comment to `## Queued Upstream Update` + queue `outstanding_questions` entry (category: `deviation-approval`). Orchestrator continues per P352. | ADR-024 amendment (P080); ADR-013 Rule 6; P352 |
|
|
361
450
|
| Above-appetite commit (Step 7) | Skip the commit, report uncommitted state. | ADR-013 Rule 6 |
|
|
451
|
+
| **Inbound-origin verdict (P363)** | When the ticket carries `**Origin**: inbound-reported (#NN)`, run the [§ Inbound-origin verdict dispatch](#inbound-origin-verdict-dispatch-p363) leg (I1–I6): idempotency-guard, then route through the SAME external-comms + voice-tone dual gate, post `gh issue comment` on our own repo (and `gh issue close` on Verifying → Closed), back-write a direction-tagged lifecycle log entry. Above-appetite queues per the rows above (does NOT halt). Reporter-facing prose only — no framework-internal vocab (P229). | ADR-024 amendment (P363); ADR-076 (Origin field); ADR-028; P352 |
|
|
362
452
|
|
|
363
453
|
The pre-amendment "halt-the-orchestrator on above-appetite" semantics are **superseded** by queue-and-continue per P352 — same shape as the post-P270 initial-filing path.
|
|
364
454
|
|
|
@@ -388,6 +478,9 @@ The skill's no-op exit (Step 1) means firing the trigger unconditionally on ever
|
|
|
388
478
|
- [ADR-075](../../../docs/decisions/075-promptfoo-agent-prose-verdict-eval-harness.proposed.md) Amendment 2026-06-02 — paired promptfoo Tier-A/B eval discharges the R009 prose-floor for SKILL surfaces.
|
|
389
479
|
- [ADR-061](../../../docs/decisions/061-dogfood-graduation-criteria.proposed.md) Rule 4 — evidence-floor; the paired eval ships in the same commit as this SKILL prose for atomic R009 discharge.
|
|
390
480
|
- **P080** — driving problem ticket (No bidirectional update of upstream-reported problems).
|
|
481
|
+
- **P363** — driving problem ticket for the [§ Inbound-origin verdict dispatch](#inbound-origin-verdict-dispatch-p363) leg (inbound-reported tickets never received a fix-released verdict on the originating issue). Fix option (b) — consume the `**Origin**` field — user-ratified 2026-06-22.
|
|
482
|
+
- [ADR-076](../../../docs/decisions/076-inbound-reported-problems-rank-ahead-via-sort-tier.proposed.md) — owns the `**Origin**: inbound-reported (#NN)` on-ticket field this leg consumes.
|
|
483
|
+
- [ADR-062](../../../docs/decisions/062-inbound-upstream-report-discovery-assessment-pipeline.proposed.md) — inbound intake-time pipeline; its safe-and-valid branch is the Origin-field writer this leg reads at fix-released time.
|
|
391
484
|
- **P079** — sibling problem (inbound-discovery leg); together P079 + P080 close the reporter-loop end-to-end.
|
|
392
485
|
- **P078** — capture-on-correction; the manage-problem trap this skill closes (manual upstream-update step gets forgotten under load).
|
|
393
486
|
- [`packages/itil/skills/report-upstream/SKILL.md`](../report-upstream/SKILL.md) — reciprocal sibling (initial-filing path); shares the `## Reported Upstream` contract this skill consumes.
|
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
# structural retrofit-via-justification when the linked harness-gap ticket
|
|
7
7
|
# has not yet shipped the primitives. The paired promptfoo eval at
|
|
8
8
|
# packages/itil/skills/update-upstream/eval/promptfooconfig.yaml carries
|
|
9
|
-
# the behavioural Tier-A/B coverage per ADR-075 Amendment 2026-06-02.
|
|
9
|
+
# the behavioural Tier-A/B coverage per ADR-075 Amendment 2026-06-02.
|
|
10
|
+
# Provenance: P080 (original bidirectional contract) + P363 / ADR-024
|
|
11
|
+
# amendment 2026-06-22 (inbound-origin verdict dispatch leg — tests 21-30,
|
|
12
|
+
# behaviourally paired by the inbound eval cases in promptfooconfig.yaml).
|
|
13
|
+
# The lockstep transition-problem/manage-problem grep check is an inherent
|
|
14
|
+
# copy-not-move drift detector (ADR-010/P362) with no behavioural form.)
|
|
10
15
|
#
|
|
11
16
|
# Doc-lint structural test (Permitted Exception per ADR-005 — structural
|
|
12
17
|
# SKILL.md content checks, not behavioural). Mirrors the doc-lint pattern
|
|
@@ -29,6 +34,8 @@ setup() {
|
|
|
29
34
|
REPO_ROOT="$(cd "$(dirname "$BATS_TEST_FILENAME")/../../../../.." && pwd)"
|
|
30
35
|
SKILL_MD="$REPO_ROOT/packages/itil/skills/update-upstream/SKILL.md"
|
|
31
36
|
EVAL_CONFIG="$REPO_ROOT/packages/itil/skills/update-upstream/eval/promptfooconfig.yaml"
|
|
37
|
+
TRANSITION_MD="$REPO_ROOT/packages/itil/skills/transition-problem/SKILL.md"
|
|
38
|
+
MANAGE_MD="$REPO_ROOT/packages/itil/skills/manage-problem/SKILL.md"
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
@test "update-upstream: SKILL.md exists" {
|
|
@@ -196,6 +203,91 @@ setup() {
|
|
|
196
203
|
[ "$status" -eq 0 ]
|
|
197
204
|
}
|
|
198
205
|
|
|
206
|
+
# ─── Inbound-origin verdict dispatch leg (P363 / ADR-024 amendment 2026-06-22) ─
|
|
207
|
+
|
|
208
|
+
@test "update-upstream: SKILL.md documents the inbound-origin verdict dispatch leg (P363)" {
|
|
209
|
+
# The skill reads the **Origin**: inbound-reported (#NN) field (ADR-076)
|
|
210
|
+
# in addition to ## Reported Upstream, so inbound reporters get a verdict.
|
|
211
|
+
run grep -iE 'Inbound-origin verdict dispatch' "$SKILL_MD"
|
|
212
|
+
[ "$status" -eq 0 ]
|
|
213
|
+
run grep -F 'inbound-reported (#NN)' "$SKILL_MD"
|
|
214
|
+
[ "$status" -eq 0 ]
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@test "update-upstream: SKILL.md no-op exit requires BOTH surfaces absent (section AND inbound Origin)" {
|
|
218
|
+
# The dual-direction no-op exit fires only when NEITHER the outbound
|
|
219
|
+
# ## Reported Upstream section NOR the inbound **Origin** field is present.
|
|
220
|
+
run grep -iE 'no inbound Origin|NEITHER .*Reported Upstream.*Origin|both are absent' "$SKILL_MD"
|
|
221
|
+
[ "$status" -eq 0 ]
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
@test "update-upstream: SKILL.md inbound leg resolves the originating issue on OUR OWN repo (not external upstream)" {
|
|
225
|
+
# Inbound issues are filed AGAINST us — the comment posts on our own repo,
|
|
226
|
+
# resolved via gh default / gh repo view, NOT an external upstream owner/repo.
|
|
227
|
+
run grep -iE 'gh repo view|our own repo|own repo' "$SKILL_MD"
|
|
228
|
+
[ "$status" -eq 0 ]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@test "update-upstream: SKILL.md inbound leg has an idempotency guard (gh issue view --json comments)" {
|
|
232
|
+
# Before posting, scan existing comments for the verdict marker
|
|
233
|
+
# (package@version + commit SHA) and skip if already posted.
|
|
234
|
+
run grep -F 'gh issue view' "$SKILL_MD"
|
|
235
|
+
[ "$status" -eq 0 ]
|
|
236
|
+
run grep -iE 'idempoten' "$SKILL_MD"
|
|
237
|
+
[ "$status" -eq 0 ]
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@test "update-upstream: SKILL.md inbound templates carry the P229 anti-leakage rule (reporter-facing, no internal vocab)" {
|
|
241
|
+
# Reporter-facing comment bodies on our own repo MUST NOT leak Step IDs,
|
|
242
|
+
# branch names, classification tokens, or P/ADR/JTBD IDs as carriers of
|
|
243
|
+
# meaning. The released @windyroad/<pkg>@<version> is the only permitted
|
|
244
|
+
# structured token. Mirrors ADR-062 safe-and-valid acknowledgement shape.
|
|
245
|
+
run grep -iE 'anti-leakage|reporter-surface prose|reporter-facing' "$SKILL_MD"
|
|
246
|
+
[ "$status" -eq 0 ]
|
|
247
|
+
run grep -F 'P229' "$SKILL_MD"
|
|
248
|
+
[ "$status" -eq 0 ]
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@test "update-upstream: SKILL.md inbound leg keeps the SAME dual gate composition (no weaker path)" {
|
|
252
|
+
# The inbound comment routes through the SAME external-comms + voice-tone
|
|
253
|
+
# dual gate as the outbound path — no weaker path for inbound.
|
|
254
|
+
run grep -iE 'SAME .*external-comms .*voice-tone|same.*dual gate' "$SKILL_MD"
|
|
255
|
+
[ "$status" -eq 0 ]
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@test "update-upstream: SKILL.md inbound Verifying→Closed also closes the own-repo issue (addresses #97-unclosed witness)" {
|
|
259
|
+
# P211 #97 was silent AND unclosed. The inbound leg runs gh issue close
|
|
260
|
+
# on the own repo on the Verifying→Closed transition.
|
|
261
|
+
run grep -iE 'posted-inbound-comment-and-closed|gh issue close .*OWN' "$SKILL_MD"
|
|
262
|
+
[ "$status" -eq 0 ]
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
@test "update-upstream: SKILL.md both-direction tickets fire both legs independently" {
|
|
266
|
+
# A ticket reported upstream AND reported against us inbound fires both
|
|
267
|
+
# dispatches independently — one above-appetite leg queues only itself.
|
|
268
|
+
run grep -iE 'Both-direction|both.*legs.*independent|fire .*independently' "$SKILL_MD"
|
|
269
|
+
[ "$status" -eq 0 ]
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
@test "update-upstream: SKILL.md back-writes inbound entries direction-tagged so P249 poller is uncontaminated" {
|
|
273
|
+
# Inbound entries log to ## Upstream Lifecycle Updates (NOT ## Reported
|
|
274
|
+
# Upstream) so /wr-itil:check-upstream-responses (P249) is not contaminated.
|
|
275
|
+
run grep -F 'P249' "$SKILL_MD"
|
|
276
|
+
[ "$status" -eq 0 ]
|
|
277
|
+
run grep -iE 'inbound.*disclosure path|posted-inbound-comment' "$SKILL_MD"
|
|
278
|
+
[ "$status" -eq 0 ]
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@test "transition-problem + manage-problem Step 7 greps match the inbound Origin alternation in LOCKSTEP (P363/P362)" {
|
|
282
|
+
# Both lockstep pre-checks must match ^## Reported Upstream OR
|
|
283
|
+
# ^\*\*Origin\*\*: inbound-reported \(# — drift re-opens the P363 gap on
|
|
284
|
+
# whichever surface lacks the alternation (ADR-010 copy-not-move / P362).
|
|
285
|
+
run grep -F 'inbound-reported \(#' "$TRANSITION_MD"
|
|
286
|
+
[ "$status" -eq 0 ]
|
|
287
|
+
run grep -F 'inbound-reported \(#' "$MANAGE_MD"
|
|
288
|
+
[ "$status" -eq 0 ]
|
|
289
|
+
}
|
|
290
|
+
|
|
199
291
|
# ─── Paired promptfoo eval (ADR-075 Amendment 2026-06-02 + ADR-061 Rule 4) ────
|
|
200
292
|
#
|
|
201
293
|
# The paired promptfoo eval at packages/itil/skills/update-upstream/eval/
|