@windyroad/jtbd 0.8.4 → 0.9.0-preview.446

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.
@@ -90,5 +90,5 @@
90
90
  }
91
91
  },
92
92
  "name": "wr-jtbd",
93
- "version": "0.8.4"
93
+ "version": "0.9.0"
94
94
  }
package/agents/agent.md CHANGED
@@ -52,8 +52,8 @@ When the change or plan under review **explicitly cites, implements, or serves**
52
52
  wr-jtbd-is-job-or-persona-unconfirmed <persona-name | JTBD-NNN>
53
53
  ```
54
54
 
55
- - **Exit 0** (frontmatter lacks the marker AND the artifact is not superseded) → the artifact is **unratified**. Emit **ISSUES FOUND / [Unratified Dependency]** with action: "ratify `<persona | JTBD-NNN>` via `/wr-jtbd:confirm-jobs-and-personas` before this lands." (The predicate prints the resolved path on stdout.)
56
- - **Exit 1** (ratified, or superseded) → do NOT flag.
55
+ - **Exit 0** (frontmatter lacks the marker AND the artifact is not superseded AND it does not carry the rejected-pending-supersede + supersede-ticket pair) → the artifact is **unratified**. Emit **ISSUES FOUND / [Unratified Dependency]** with action: "ratify `<persona | JTBD-NNN>` via `/wr-jtbd:confirm-jobs-and-personas` before this lands." (The predicate prints the resolved path on stdout.)
56
+ - **Exit 1** (ratified, superseded, or rejected-pending-supersede with a tracked `supersede-ticket: P<NNN>` — ADR-068 amendment per P316) → do NOT flag. A user-rejected artifact with a tracked supersede ticket is ratified-equivalent for the build-upon guard.
57
57
  - **Exit 2** (ref not found) → the change cites a persona/job that does not exist; that is a separate Job Gap / Persona Mismatch, not an Unratified Dependency.
58
58
 
59
59
  **Key the flag on the oversight marker, NEVER on `status:`.** `status: proposed`/`accepted` and `human-oversight:` are orthogonal axes (ADR-066). Building on a **ratified** job whose `status` is still `proposed` is fine — do NOT flag it; only the *unratified* (marker-absent, non-superseded) case flags.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@windyroad/jtbd",
3
- "version": "0.8.4",
3
+ "version": "0.9.0-preview.446",
4
4
  "description": "Jobs-to-be-done enforcement for UI changes",
5
5
  "bin": {
6
6
  "windyroad-jtbd": "./bin/install.mjs"
@@ -41,7 +41,18 @@ for f in "$JTBD_DIR"/*/*.md "$JTBD_DIR"/*.md; do
41
41
  { print }
42
42
  ' "$f")"
43
43
 
44
- if ! printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*confirmed[[:space:]]*$'; then
45
- echo "$f"
44
+ if printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*confirmed[[:space:]]*$'; then
45
+ continue
46
46
  fi
47
+
48
+ # ADR-068 amendment (P316): mirror the architect detector's
49
+ # rejected-pending-supersede exclusion. Both the marker AND a
50
+ # supersede-ticket: P<NNN> scalar must be present; an un-ticketed marker
51
+ # still surfaces (defensive — preserves JTBD-201/202 audit-trail guard).
52
+ if printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*rejected-pending-supersede[[:space:]]*$' \
53
+ && printf '%s\n' "$fm" | grep -qiE '^supersede-ticket:[[:space:]]*P[0-9]+[[:space:]]*$'; then
54
+ continue
55
+ fi
56
+
57
+ echo "$f"
47
58
  done | sort
@@ -84,6 +84,16 @@ if printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*confirmed[[:spa
84
84
  exit 1 # confirmed — OK to build on
85
85
  fi
86
86
 
87
+ # ADR-068 amendment (P316): mirror the architect predicate's
88
+ # rejected-pending-supersede exclusion. A persona/job the user explicitly
89
+ # rejected with a tracked supersede ticket is ratified-equivalent for the
90
+ # build-upon guard — the [Unratified Dependency] verdict must NOT re-fire on
91
+ # it. Marker without ticket still fires (defensive).
92
+ if printf '%s\n' "$fm" | grep -qiE '^human-oversight:[[:space:]]*rejected-pending-supersede[[:space:]]*$' \
93
+ && printf '%s\n' "$fm" | grep -qiE '^supersede-ticket:[[:space:]]*P[0-9]+[[:space:]]*$'; then
94
+ exit 1
95
+ fi
96
+
87
97
  # Unconfirmed — the build-upon guard SHOULD fire. Name the file for the guard.
88
98
  echo "$file"
89
99
  exit 0
@@ -83,3 +83,31 @@ mk() { # mk <relpath under docs/jtbd> <extra frontmatter lines...>
83
83
  [ "$status" -eq 0 ]
84
84
  [ -z "$output" ]
85
85
  }
86
+
87
+ # ADR-068 amendment (P316): mirror the architect `rejected-pending-supersede`
88
+ # exclusion onto the JTBD detector. Exclusion requires BOTH the marker AND
89
+ # a supersede-ticket: P<NNN> scalar; a marker without the ticket is
90
+ # malformed and still surfaces (defensive).
91
+
92
+ @test "JTBD with rejected-pending-supersede + supersede-ticket is excluded" {
93
+ mk "solo-developer/JTBD-020-rejected.proposed.md" \
94
+ "human-oversight: rejected-pending-supersede" \
95
+ "supersede-ticket: P297"
96
+ run bash "$SCRIPT" "$DIR/docs/jtbd"
97
+ [[ "$output" != *"JTBD-020-rejected.proposed.md"* ]]
98
+ }
99
+
100
+ @test "JTBD with rejected-pending-supersede WITHOUT supersede-ticket still surfaces (defensive)" {
101
+ mk "solo-developer/JTBD-021-untracked.proposed.md" \
102
+ "human-oversight: rejected-pending-supersede"
103
+ run bash "$SCRIPT" "$DIR/docs/jtbd"
104
+ [[ "$output" == *"JTBD-021-untracked.proposed.md"* ]]
105
+ }
106
+
107
+ @test "persona with rejected-pending-supersede + ticket is also excluded" {
108
+ mk "rejected-persona/persona.md" \
109
+ "human-oversight: rejected-pending-supersede" \
110
+ "supersede-ticket: P299"
111
+ run bash "$SCRIPT" "$DIR/docs/jtbd"
112
+ [[ "$output" != *"rejected-persona/persona.md"* ]]
113
+ }
@@ -124,3 +124,44 @@ mk_job() {
124
124
  [[ "$detect_out" != *"tech-lead/persona.md"* ]]
125
125
  run bash "$SCRIPT" "tech-lead" "$DIR/docs/jtbd"; [ "$status" -eq 1 ]
126
126
  }
127
+
128
+ # ADR-068 amendment (P316): mirror the architect `rejected-pending-supersede`
129
+ # exclusion onto the JTBD predicate.
130
+
131
+ # mk_rejected_persona <name> [supersede-ticket-or-empty]
132
+ mk_rejected_persona() {
133
+ local name="$1"; local ticket="${2:-}"
134
+ mkdir -p "$DIR/docs/jtbd/$name"
135
+ {
136
+ echo "---"
137
+ echo "name: $name"
138
+ echo "human-oversight: rejected-pending-supersede"
139
+ [ -n "$ticket" ] && echo "supersede-ticket: $ticket"
140
+ echo "---"
141
+ echo "# $name"
142
+ } > "$DIR/docs/jtbd/$name/persona.md"
143
+ }
144
+
145
+ @test "persona with rejected-pending-supersede + supersede-ticket does NOT fire the guard (exit 1)" {
146
+ mk_rejected_persona "scrapped-persona" "P299"
147
+ run bash "$SCRIPT" "scrapped-persona" "$DIR/docs/jtbd"
148
+ [ "$status" -eq 1 ]
149
+ [ -z "$output" ]
150
+ }
151
+
152
+ @test "persona with rejected-pending-supersede WITHOUT supersede-ticket DOES fire the guard (exit 0)" {
153
+ mk_rejected_persona "untracked-persona" ""
154
+ run bash "$SCRIPT" "untracked-persona" "$DIR/docs/jtbd"
155
+ [ "$status" -eq 0 ]
156
+ [[ "$output" == *"untracked-persona/persona.md"* ]]
157
+ }
158
+
159
+ @test "agrees with detect-unoversighted on rejected-pending-supersede (sync guard)" {
160
+ mk_rejected_persona "alpha-tracked" "P297"
161
+ mk_rejected_persona "beta-untracked" ""
162
+ detect_out="$(bash "$DETECT" "$DIR/docs/jtbd")"
163
+ [[ "$detect_out" != *"alpha-tracked/persona.md"* ]]
164
+ run bash "$SCRIPT" "alpha-tracked" "$DIR/docs/jtbd"; [ "$status" -eq 1 ]
165
+ [[ "$detect_out" == *"beta-untracked/persona.md"* ]]
166
+ run bash "$SCRIPT" "beta-untracked" "$DIR/docs/jtbd"; [ "$status" -eq 0 ]
167
+ }
@@ -42,7 +42,7 @@ For each job/persona in the ordered queue, surface it as an `AskUserQuestion` (c
42
42
  - **Options** per artifact:
43
43
  - **Confirm** — the job/persona accurately reflects real need; write the marker.
44
44
  - **Amend** — mostly right but needs a change; capture it, apply it to the file, then write the marker.
45
- - **Reject** — the auto-derived job/persona does not reflect real need; do NOT write the marker. Note the rework (a `wr-jtbd:update-guide` rewrite, or retirement).
45
+ - **Reject** — the auto-derived job/persona does not reflect real need; capture the supersede ticket (see Step 4) and write the **rejected-pending-supersede** marker so the drain stops re-asking.
46
46
  - **Defer** — skip this sitting; leave unoversighted for later.
47
47
 
48
48
  This is a genuine human-decision surface (the point of P288/ADR-068) — `AskUserQuestion` is correct here, not over-asking. Do not auto-confirm; do not prose-ask.
@@ -50,7 +50,10 @@ This is a genuine human-decision surface (the point of P288/ADR-068) — `AskUse
50
50
  ### Step 4: Apply the outcome
51
51
 
52
52
  - **Confirm / Amend**: write `human-oversight: confirmed` + `oversight-date: <today, YYYY-MM-DD>` into the file's frontmatter (insert after the `status:`/`date-created:` line if absent; never duplicate). For Amend, apply the directed change first. Edits go through the standard JTBD / architect edit gate per ADR-014.
53
- - **Reject**: leave the marker absent; record the rework.
53
+ - **Reject** (ADR-068 amendment per P316, mirroring ADR-066):
54
+ 1. Capture the supersede ticket via a follow-up `AskUserQuestion`: "Which problem ticket tracks the rework?" — options: existing `P<NNN>` IDs surfaced from `docs/problems/`, **Capture a new ticket** (delegate to `/wr-itil:capture-problem`), or **Defer (leave un-tracked for now)**.
55
+ 2. If a ticket ID is captured, write `human-oversight: rejected-pending-supersede` + `supersede-ticket: P<NNN>` into the file's frontmatter. The detector excludes artifacts carrying both, so the drain stops re-asking until either the rework lands (file renamed to `*.superseded.md`) or the rejection is revisited.
56
+ 3. If the user defers ticket capture, leave the marker absent — the artifact re-surfaces next drain (the un-tracked case is intentionally re-asked so it doesn't silently rot).
54
57
  - **Defer**: no write.
55
58
 
56
59
  **Unoversighted ≠ unusable** (ADR-068): an unconfirmed job/persona stays fully readable and review-anchorable. The marker records provenance; it never quarantines the doc or blocks reviews from reading it.
@@ -61,7 +64,7 @@ Commit the confirmed/amended files per ADR-014 (one commit per drain sitting is
61
64
 
62
65
  ## Notes
63
66
 
64
- - **Never re-ask** — a confirmed job/persona carries the marker permanently and is excluded from future runs (ADR-009). Write-once **except** when the job statement / persona definition is materially rewritten — a material amend clears the marker for re-confirmation (ADR-068 Reassessment).
67
+ - **Never re-ask** — a confirmed job/persona carries the marker permanently and is excluded from future runs (ADR-009). The same write-once-permanence applies to the `rejected-pending-supersede` value (P316 amendment): once the user rejects with a tracked ticket, the drain stops asking. Write-once **except** when the job statement / persona definition is materially rewritten — a material amend clears the marker for re-confirmation (ADR-068 Reassessment). When the rework lands and the file is renamed to `*.superseded.md`, the existing superseded-name skip takes over; the `rejected-pending-supersede` lines become historical residue.
65
68
  - **AFK** — interactive by construction (the confirm IS the human decision); not dispatched in AFK iteration subprocesses. The session-start nudge self-suppresses there (`WR_SUPPRESS_OVERSIGHT_NUDGE=1`).
66
69
  - **Born-confirmed going forward** — `/wr-jtbd:update-guide` writes the marker when the user confirms a new/edited job or persona, so new artifacts enter the set already oversighted and the unoversighted count only shrinks.
67
70