@thehammer/danx-dashboard-mcp 0.1.84 → 0.1.85

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.
Files changed (2) hide show
  1. package/dist/listen.js +42 -0
  2. package/package.json +1 -1
package/dist/listen.js CHANGED
@@ -122,6 +122,32 @@ export function invalidEventReason(value) {
122
122
  }
123
123
  return null;
124
124
  }
125
+ // DX-2935 — the operator retracted a problem's answer with no new one yet.
126
+ case "problem_unanswered": {
127
+ const problem = d.problem;
128
+ if (!isRecord(problem) || typeof problem.id !== "number" || !isCappedText(problem.statement)) {
129
+ return "detail.problem is not {id, statement}";
130
+ }
131
+ return typeof d.decision_id === "number" ? null : "detail.decision_id is not a number";
132
+ }
133
+ // DX-2935 — the operator retracted a problem's answer AND recorded a new
134
+ // one, in one transaction — same either/or solution/freeform shape
135
+ // `solution_answered` carries, plus which decision was retracted.
136
+ case "problem_answer_changed": {
137
+ const problem = d.problem;
138
+ if (!isRecord(problem) || typeof problem.id !== "number" || !isCappedText(problem.statement)) {
139
+ return "detail.problem is not {id, statement}";
140
+ }
141
+ if (typeof d.retracted_decision_id !== "number")
142
+ return "detail.retracted_decision_id is not a number";
143
+ if (typeof d.decision_id !== "number")
144
+ return "detail.decision_id is not a number";
145
+ if (d.solution === null)
146
+ return isCappedText(d.freeform) ? null : "detail.freeform is not capped text";
147
+ if (!isRecord(d.solution) || typeof d.solution.title !== "string")
148
+ return "detail.solution is not {title, note}";
149
+ return d.solution.note === null || isCappedText(d.solution.note) ? null : "detail.solution.note is not capped text";
150
+ }
125
151
  case "blocked":
126
152
  return isCappedText(d.reason) ? null : "detail.reason is not capped text";
127
153
  default:
@@ -160,6 +186,22 @@ function describe(event) {
160
186
  const problem = d.problem;
161
187
  return `${event.actor} opened a problem: ${quoted(problem.statement)}`;
162
188
  }
189
+ case "problem_unanswered": {
190
+ // DX-2935 — MUST read as "a previous answer was withdrawn", never as a
191
+ // brand-new problem: a connected session that already acted on the
192
+ // retracted answer has to stop, not treat this as fresh work to start.
193
+ const problem = d.problem;
194
+ return `${event.actor} retracted the answer to ${quoted(problem.statement)}`;
195
+ }
196
+ case "problem_answer_changed": {
197
+ // DX-2935 — ONE line for the whole retract-and-reanswer (never two
198
+ // separate events), naming the statement so a listener with several
199
+ // open questions knows which one just moved.
200
+ const problem = d.problem;
201
+ const solution = d.solution;
202
+ const now = solution === null ? quoted(d.freeform) : `"${solution.title}"`;
203
+ return `${event.actor} changed the answer to ${quoted(problem.statement)}: now ${now}`;
204
+ }
163
205
  case "blocked":
164
206
  return `${event.actor} blocked the card: ${quoted(d.reason)}`;
165
207
  case "unblocked":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thehammer/danx-dashboard-mcp",
3
- "version": "0.1.84",
3
+ "version": "0.1.85",
4
4
  "description": "Stdio MCP server wrapping danxbot's dashboard /api/issues/* normalized DB-backed HTTP routes for dispatched agents (DX-704 Phase 2).",
5
5
  "license": "MIT",
6
6
  "type": "module",