@thehammer/danx-dashboard-mcp 0.1.115 → 0.1.116
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/dist/handlers.js +11 -1
- package/dist/index.js +35 -14
- package/package.json +1 -1
package/dist/handlers.js
CHANGED
|
@@ -619,6 +619,11 @@ export async function issueProblem(client, args) {
|
|
|
619
619
|
// doesn't yet know about this field).
|
|
620
620
|
if (args.type !== undefined)
|
|
621
621
|
body.type = args.type;
|
|
622
|
+
// DX-3309 (follow-up) — sent only when given; the server itself refuses
|
|
623
|
+
// an `action` add with no summary (400 naming the field), and defaults
|
|
624
|
+
// an omitted `question` summary to absent (`null`).
|
|
625
|
+
if (args.summary !== undefined)
|
|
626
|
+
body.summary = args.summary;
|
|
622
627
|
if (args.solutions !== undefined)
|
|
623
628
|
body.solutions = args.solutions;
|
|
624
629
|
const result = await client.request({ method: "POST", path: `/${idEnc}/problems`, body, board });
|
|
@@ -631,7 +636,12 @@ export async function issueProblem(client, args) {
|
|
|
631
636
|
return client.request({
|
|
632
637
|
method: "PATCH",
|
|
633
638
|
path: `/${idEnc}/problems/${problemId}`,
|
|
634
|
-
body: {
|
|
639
|
+
body: {
|
|
640
|
+
base_hash: baseHash,
|
|
641
|
+
statement,
|
|
642
|
+
...(args.context === undefined ? {} : { context: args.context }),
|
|
643
|
+
...(args.summary === undefined ? {} : { summary: args.summary }),
|
|
644
|
+
},
|
|
635
645
|
board,
|
|
636
646
|
});
|
|
637
647
|
}
|
package/dist/index.js
CHANGED
|
@@ -610,33 +610,54 @@ const SOLUTION_FIELDS = {
|
|
|
610
610
|
con: z.string().optional(),
|
|
611
611
|
recommended: z.boolean().optional(),
|
|
612
612
|
};
|
|
613
|
-
strictTool("issue_problem", "A card's PROBLEMS via /api/issues/:id/problems[/:pid]: one statement the operator must resolve (a question, or a flaw in the plan), each with its own solutions/answers — one problem per question. OPEN = not yet answered; the card needs a human exactly while open_problem_count > 0 — there is no separate flag to set, adding a problem IS putting the card in front of a human. list → live problems in order, each {id, statement, context, type, content_hash, open, solutions[], decisions[]}; add {statement, context?, type?, solutions?} → problem_id + solution_ids in one transaction (zero solutions is valid: the operator answers free-form) plus `problems_reminder: {open_problem_count, instruction}` naming each open problem's solution count; edit :pid {base_hash, statement, context?}; remove :pid {base_hash} — always allowed, even as the card's last open problem (DX-2830: removing it just means the card no longer needs a human). A stale base_hash → 409 `stale_problem` with currentHash + currentProblem: merge, then retry. No answer action — the operator answers in the dashboard. DX-2942 — `statement` is capped at 200 characters (a 400 names the actual length otherwise): write it as ONE plain question, and put any investigation detail in `context` (markdown, no cap) instead of running it on. Good: statement \"Which cache should we use?\", context \"Redis fits the read-heavy path; see benchmark in #123. Memcached is simpler ops but no persistence.\" Bad: statement \"We looked at Redis vs Memcached, ran benchmarks showing Redis 3x faster on reads, but Memcached has simpler ops and we're not sure persistence matters here since the cache is fully rebuildable from Postgres...\" (too long, refused — move it to context). DX-3309 — every problem is also a `type
|
|
613
|
+
strictTool("issue_problem", "A card's PROBLEMS via /api/issues/:id/problems[/:pid]: one statement the operator must resolve (a question, or a flaw in the plan) OR an action only a person can carry out, each with its own solutions/answers — one problem per question. OPEN = not yet answered; the card needs a human exactly while open_problem_count > 0 — there is no separate flag to set, adding a problem IS putting the card in front of a human. list → live problems in order, each {id, statement, context, type, summary, content_hash, open, solutions[], decisions[]}; add {statement, context?, type?, summary?, solutions?} → problem_id + solution_ids in one transaction (zero solutions is valid: the operator answers free-form) plus `problems_reminder: {open_problem_count, instruction}` naming each open problem's solution count; edit :pid {base_hash, statement, context?, summary?}; remove :pid {base_hash} — always allowed, even as the card's last open problem (DX-2830: removing it just means the card no longer needs a human). A stale base_hash → 409 `stale_problem` with currentHash + currentProblem: merge, then retry. No answer action — the operator answers in the dashboard. DX-2942 — `statement` is capped at 200 characters (a 400 names the actual length otherwise): write it as ONE plain sentence (a question for a question, the deed itself for an action), and put any investigation detail in `context` (markdown, no cap) instead of running it on. Good: statement \"Which cache should we use?\", context \"Redis fits the read-heavy path; see benchmark in #123. Memcached is simpler ops but no persistence.\" Bad: statement \"We looked at Redis vs Memcached, ran benchmarks showing Redis 3x faster on reads, but Memcached has simpler ops and we're not sure persistence matters here since the cache is fully rebuildable from Postgres...\" (too long, refused — move it to context). DX-3309 — every problem is also a `type`, and DX-3309's follow-up gave it a `summary` distinct from `context`: read BOTH fields' own descriptions below before your first `add` — together they teach which type this is, and the three-field split (`statement` / `summary` / `context`) an action actually needs.", {
|
|
614
614
|
id: z.string().min(1),
|
|
615
615
|
action: z.enum(["list", "add", "edit", "remove"]),
|
|
616
616
|
problem_id: z.number().int().positive().optional().describe("edit/remove"),
|
|
617
617
|
base_hash: z.string().min(1).optional().describe("content_hash last read; edit/remove"),
|
|
618
|
-
statement: z
|
|
618
|
+
statement: z
|
|
619
|
+
.string()
|
|
620
|
+
.min(1)
|
|
621
|
+
.optional()
|
|
622
|
+
.describe("add/edit; ONE plain sentence, at most 200 characters. For a question: the question itself. For an action: " +
|
|
623
|
+
"WHAT IS TO BE DONE — the deed itself, never phrased as a question (\"Rotate the staging DB credential\", " +
|
|
624
|
+
"not \"Should we rotate it?\")."),
|
|
619
625
|
context: z
|
|
620
626
|
.string()
|
|
621
627
|
.nullable()
|
|
622
628
|
.optional()
|
|
623
|
-
.describe("add/edit; markdown detail behind statement — file:line refs, code excerpts, root-cause writeups
|
|
629
|
+
.describe("add/edit; markdown detail behind statement — file:line refs, code excerpts, root-cause writeups, or (for " +
|
|
630
|
+
"an action) whatever detail the person carrying it out needs. NOT where an action's why-can't-the-agent " +
|
|
631
|
+
"sentence goes — that is `summary`. add: sent only when given (null/omit means none). edit: omit to keep " +
|
|
632
|
+
"the stored context, null to clear it."),
|
|
624
633
|
type: z
|
|
625
634
|
.enum(["question", "action"])
|
|
626
635
|
.optional()
|
|
627
636
|
.describe("add only. Before you raise this problem, apply the test: could I do this myself if I tried harder, and is the " +
|
|
628
637
|
"only thing missing a decision? If yes, this is a \"question\": statement is the question itself (one plain " +
|
|
629
|
-
"sentence); context is the evidence behind it; solutions[] are
|
|
630
|
-
"and the operator is done the moment they pick one. If the
|
|
631
|
-
"human's authority, or a system you genuinely cannot reach,
|
|
632
|
-
"BE DONE — the deed itself, never phrased as a question
|
|
633
|
-
"we rotate it?\");
|
|
634
|
-
"
|
|
635
|
-
"
|
|
636
|
-
"
|
|
637
|
-
"
|
|
638
|
-
"
|
|
639
|
-
"
|
|
638
|
+
"sentence); summary (optional) is why it matters; context is the evidence behind it; solutions[] are " +
|
|
639
|
+
"candidate ANSWERS, each with its own pro/con, and the operator is done the moment they pick one. If the " +
|
|
640
|
+
"blocker is access, credentials, hardware, a human's authority, or a system you genuinely cannot reach, " +
|
|
641
|
+
"this is an \"action\": statement is WHAT IS TO BE DONE — the deed itself, never phrased as a question " +
|
|
642
|
+
"(\"Rotate the staging DB credential\", not \"Should we rotate it?\"); summary is REQUIRED and MUST say " +
|
|
643
|
+
"WHY THE ACTION IS NEEDED AND WHY YOU CANNOT DO IT YOURSELF — that sentence is what tells the operator this " +
|
|
644
|
+
"is not you being lazy (an add with no summary is refused 400); context is whatever additional detail the " +
|
|
645
|
+
"person needs to carry it out; solutions[] are the possible ROUTES a person could take (e.g. \"rotate by " +
|
|
646
|
+
"hand in the console\" vs \"run the provisioning script\" vs \"ask the vendor\") — each will carry its own " +
|
|
647
|
+
"ordered steps to completion once the operator picks one (a later release; for now, describe the route in " +
|
|
648
|
+
"the solution's body). Omitted defaults to \"question\" (today's behavior) — but that default exists for " +
|
|
649
|
+
"the caller who has never heard of this field, not as permission to skip the choice: decide deliberately " +
|
|
650
|
+
"every time."),
|
|
651
|
+
summary: z
|
|
652
|
+
.string()
|
|
653
|
+
.nullable()
|
|
654
|
+
.optional()
|
|
655
|
+
.describe("add/edit. Plain text, 1-3 sentences — never markdown detail (that's `context`'s job). For a question: " +
|
|
656
|
+
"optional, why it matters. For an action: REQUIRED and non-empty — why the action is needed AND why you " +
|
|
657
|
+
"(the agent raising it) cannot do it yourself; omitting it on an action add is refused 400 naming this " +
|
|
658
|
+
"field, and an edit that would clear it on a live action problem is refused the same way. add: sent only " +
|
|
659
|
+
"when given (omit/null on a question means none). edit: omit to keep the stored summary, null to clear it " +
|
|
660
|
+
"(refused if the problem is a live action)."),
|
|
640
661
|
solutions: z
|
|
641
662
|
.array(z.object({ title: z.string().min(1), ...SOLUTION_FIELDS }).strict())
|
|
642
663
|
.optional()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thehammer/danx-dashboard-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.116",
|
|
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",
|