pipebrain-mcp 0.23.0 → 0.25.0

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/main.js +10 -9
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -15254,6 +15254,7 @@ var issueSchema = external_exports.object({
15254
15254
  });
15255
15255
  var criterionFiledBugSchema = external_exports.object({
15256
15256
  id: uuidSchema,
15257
+ projectKey: projectKeySchema,
15257
15258
  displayId: external_exports.string().min(1),
15258
15259
  title: external_exports.string().min(1),
15259
15260
  status: issueStatusSchema
@@ -17000,7 +17001,7 @@ Every loose end has one destination, and none of them is prose. Anything you not
17000
17001
  run(async () => ({ items: await client2.listWaiting() }))
17001
17002
  ));
17002
17003
  registerTool("get_work_context", {
17003
- description: "Everything a session needs before it starts work, in ONE read \u2014 assembled by the API and returned verbatim. Addressed by `issue` OR by `project`, never both and never neither: an issue names its own project, so the pair is refused rather than resolved for you (\xA77). Given an ISSUE: that issue\u2019s full detail \u2014 the same payload `get_issue` returns \u2014 PLUS the BODY TEXT of every requirement it links, AT THE REVISION THE LINK IS PINNED AT. That text is the round trip this removes: `get_issue` names which documents bind the work and at which revision, never what they SAY, so a session that has read the issue still owes one fetch per link \u2014 and the one it skips leaves it building against rules it never read. Comments come CAPPED at the newest `commentLimit`, with `commentCount` \u2014 the issue\u2019s TRUE total \u2014 beside them, so a shortened list reads AS shortened rather than as the whole history; read the issue directly for the rest. Given a PROJECT: `available`, the work a session could START right now. It EXCLUDES finished and abandoned work (`done`, `killed`), work another person has claimed, and anything blocked \u2014 the status guard would refuse to start that, and offering work that cannot be started is offering a refusal. Your OWN claims stay, and so does unscheduled work carrying no milestone. The item form carries no `available`; the project form carries no item. BOTH forms also carry the project half: the release currently being worked (the active milestone) and the project\u2019s cross-cutting requirements WITH their text \u2014 they bind every epic automatically, and each is otherwise a separate call a session can simply forget to make. READ-ONLY \u2014 this claims nothing, moves nothing and writes nothing.",
17004
+ description: "Everything a session needs before it starts work, in ONE read \u2014 assembled by the API and returned verbatim. Addressed by `issue` OR by `project`, never both and never neither: an issue names its own project, so the pair is refused rather than resolved for you (\xA77). Given an ISSUE: that issue\u2019s full detail \u2014 the same payload `get_issue` returns \u2014 PLUS the BODY TEXT of every requirement it links, AT THE REVISION THE LINK IS PINNED AT. That text is the round trip this removes: `get_issue` names which documents bind the work and at which revision, never what they SAY, so a session that has read the issue still owes one fetch per link \u2014 and the one it skips leaves it building against rules it never read. Comments come CAPPED at the newest `commentLimit`, with `commentCount` \u2014 the issue\u2019s TRUE total \u2014 beside them, so a shortened list reads AS shortened rather than as the whole history; read the issue directly for the rest. Given a PROJECT: `available`, the work a session could START right now. It EXCLUDES finished and abandoned work (`done`, `killed`), work another person has claimed, and anything blocked \u2014 the status guard would refuse to start that, and offering work that cannot be started is offering a refusal. Your OWN claims stay, and so does unscheduled work carrying no milestone. The item form carries no `available`; the project form carries no item. BOTH forms also carry the project half: the release currently being worked (the active milestone) and the project\u2019s cross-cutting requirements WITH their text \u2014 they bind every epic automatically, and each is otherwise a separate call a session can simply forget to make. READ-ONLY \u2014 this claims nothing, moves nothing and writes nothing. CALL IT when you begin a piece of work, or when you pick work up in a project \u2014 the whole pack, once, before you start. Read narrowly the rest of the time; that is the ordinary case and needs no justification.",
17004
17005
  // The WHOLE domain schema rather than its `.shape`: the exactly-one-of rule is a
17005
17006
  // refinement on the OBJECT, and a raw shape drops it — the SDK validates against
17006
17007
  // what it is handed, so the shape alone would quietly accept both arguments and
@@ -17094,26 +17095,26 @@ Every loose end has one destination, and none of them is prose. Anything you not
17094
17095
  (args) => run(() => client2.listIssues(args.status === void 0 ? { ...args, status: [...OPEN_STATUSES] } : args))
17095
17096
  );
17096
17097
  registerTool("get_issue", {
17097
- description: "Full issue detail by display id or uuid: body, criteria (states, modes, evidence), explicit requirement links (pinned revision + staleness), the project\u2019s cross-cutting requirements at their latest approved revision, children, and comments (\xA77). Carries `terminal`: true when the issue is finished (`done`) or deliberately abandoned (`killed`) and is therefore NOT buildable work \u2014 check it before acting on an issue you were handed by key. Cross-cutting requirements bind every epic automatically and arrive with this payload at their latest approved revision \u2014 never restate them in a body; explicit requirement links pin the approved revision, so link by key rather than pasting a document\u2019s text.",
17098
+ description: "Full issue detail by display id or uuid: body, criteria (states, modes, evidence), explicit requirement links (pinned revision + staleness), the project\u2019s cross-cutting requirements at their latest approved revision, children, and comments (\xA77). Carries `terminal`: true when the issue is finished (`done`) or deliberately abandoned (`killed`) and is therefore NOT buildable work \u2014 check it before acting on an issue you were handed by key. Cross-cutting requirements bind every epic automatically and arrive with this payload at their latest approved revision \u2014 never restate them in a body; explicit requirement links pin the approved revision, so link by key rather than pasting a document\u2019s text. Reading criterion state: `state_evidence` is required only when a TOKEN sets one, so a `manual` criterion \u2014 settable only from a web session \u2014 carries none by design, and the attribution the server already stores (who set it, and when) IS its record. Absent evidence there is the human gate working rather than a gap: do not report it as a finding, do not call the criterion unverified or unevidenced, and do not weigh it below an `auto` criterion that carries evidence. What this payload tells you about ANOTHER issue goes stale. Reference that issue by key and say what you need from it; never restate its status, its criteria, or whether those criteria passed \u2014 such a sentence is true when written and wrong later, and a terminal issue is never revisited to correct it, so the stale reading is what the next reader inherits.",
17098
17099
  inputSchema: { issue: issueRefSchema }
17099
17100
  }, (args) => run(() => client2.getIssue(args.issue)));
17100
17101
  registerTool("create_issue", {
17101
- description: 'Create an issue (epic/task/bug/feedback). Omitted status defaults to triage (still subject to \xA76 guards); omitted environment resolves explicit \u2192 parent\u2019s environment \u2192 project default (prod). Optional parent (self/cycle rejected), priority, milestone, requirement_links (pins each at its approved revision; a target with no approved revision is rejected), deliverable_links (content deliverables like DWB-C3/bsky \u2014 pins each at its current revision; the promotion path), and ordered {text, verification, howTo} criteria (\xA77). A `status` other than `triage` or `killed` REQUIRES `milestone` (PIPE-R10 rule 9): work past triage belongs to a release, and the create is refused (`milestone_required`) without one. Search before you create: `list_issues` takes a `text` filter \u2014 run it on the distinctive nouns first. Sessions do not see each other, so a duplicate is invisible until someone finds both; on a near match, comment or amend the existing record rather than filing again. The bar for filing a bug: file `type: bug` only when the observed behavior breaks an approved requirement or a defined acceptance criterion, and name which one before you file. If you cannot name one, this is not a bug \u2014 code you find unclear, an edge case nobody specified, a performance number nobody set, and anything you would phrase as "this could be better" are opinions about the product, so file each as `type: feedback`, or not at all. The bar exists because a queue holding both real defects and unshared taste has to be read entirely before any of it can be trusted. When the criterion you named is an acceptance criterion, pass its uuid as `criterionId` and the bug records which criterion it was filed against \u2014 the criterion then names the bug (it arrives as `filedBugs` on every criteria read) instead of inviting the next reader to file it again. Bugs only: any other type naming a criterion is refused (`criterion_requires_bug`). Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Criteria live on epics only: a task cannot carry a criteria list and instead states in its own body what would count as done. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17102
+ description: 'Create an issue (epic/task/bug/feedback). Omitted status defaults to triage (still subject to \xA76 guards); omitted environment resolves explicit \u2192 parent\u2019s environment \u2192 project default (prod). Optional parent (self/cycle rejected), priority, milestone, requirement_links (pins each at its approved revision; a target with no approved revision is rejected), deliverable_links (content deliverables like DWB-C3/bsky \u2014 pins each at its current revision; the promotion path), and ordered {text, verification, howTo} criteria (\xA77). A `status` other than `triage` or `killed` REQUIRES `milestone` (PIPE-R10 rule 9): work past triage belongs to a release, and the create is refused (`milestone_required`) without one. Search before you create: `list_issues` takes a `text` filter \u2014 run it on the distinctive nouns first. Sessions do not see each other, so a duplicate is invisible until someone finds both; on a near match, comment or amend the existing record rather than filing again. The bar for filing a bug: file `type: bug` only when the observed behavior breaks an approved requirement or a defined acceptance criterion, and name which one before you file. If you cannot name one, this is not a bug \u2014 code you find unclear, an edge case nobody specified, a performance number nobody set, and anything you would phrase as "this could be better" are opinions about the product, so file each as `type: feedback`, or not at all. The bar exists because a queue holding both real defects and unshared taste has to be read entirely before any of it can be trusted. When the criterion you named is an acceptance criterion, pass its uuid as `criterionId` and the bug records which criterion it was filed against \u2014 the criterion then names the bug (it arrives as `filedBugs` on every criteria read) instead of inviting the next reader to file it again. Bugs only: any other type naming a criterion is refused (`criterion_requires_bug`). Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Work of any kind carries criteria \u2014 an epic, a task, a bug \u2014 because what they answer is how anyone knows the thing is done, and that question does not get easier as the work gets smaller; feedback is the one exception, refused with `criteria_not_supported`, because it is a report rather than agreed work and `promote_feedback` retypes it into work before anything is built. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17102
17103
  inputSchema: createIssueInputSchema.shape
17103
17104
  }, (args) => run(() => client2.createIssue(args)));
17104
17105
  registerTool("promote_feedback", {
17105
- description: 'Promote a FEEDBACK issue into a NEW epic or task (PIPE-143): creates the issue in the feedback\u2019s project (`title` + `type` required; omitted environment inherits the FEEDBACK\u2019s environment, not the project default; optional status/body/priority/milestone/requirement_links/criteria as in create_issue), records the feedback as its permanent source (`promotedFrom`/`promotedTo` on both details), closes the feedback as done, and comments the new key on it. The feedback\u2019s own title/body are never touched \u2014 write the new issue\u2019s body as real work, do not paste the feedback in. Rejected (409) for non-feedback, terminal, or already-promoted sources. Returns the created issue. A `status` other than `triage` or `killed` REQUIRES `milestone` (PIPE-R10 rule 9), exactly as in create_issue; the SOURCE feedback needs none to be closed by the promotion. Search before you promote: `list_issues` takes a `text` filter \u2014 run it on the feedback\u2019s distinctive nouns first; an issue covering it may already exist, and sessions do not see each other. On a near match, comment on or amend the existing issue rather than promoting a duplicate. The bar for promoting to a bug: choose `type: bug` only when the reported behavior breaks an approved requirement or a defined acceptance criterion, and name which one. If you cannot name one, promote it as `task` \u2014 or leave it as feedback. A queue holding both real defects and unshared taste has to be read entirely before any of it can be trusted. Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Criteria live on epics only: a task cannot carry a criteria list and instead states in its own body what would count as done. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17106
+ description: 'Promote a FEEDBACK issue into a NEW epic or task (PIPE-143): creates the issue in the feedback\u2019s project (`title` + `type` required; omitted environment inherits the FEEDBACK\u2019s environment, not the project default; optional status/body/priority/milestone/requirement_links/criteria as in create_issue), records the feedback as its permanent source (`promotedFrom`/`promotedTo` on both details), closes the feedback as done, and comments the new key on it. The feedback\u2019s own title/body are never touched \u2014 write the new issue\u2019s body as real work, do not paste the feedback in. Rejected (409) for non-feedback, terminal, or already-promoted sources. Returns the created issue. A `status` other than `triage` or `killed` REQUIRES `milestone` (PIPE-R10 rule 9), exactly as in create_issue; the SOURCE feedback needs none to be closed by the promotion. Search before you promote: `list_issues` takes a `text` filter \u2014 run it on the feedback\u2019s distinctive nouns first; an issue covering it may already exist, and sessions do not see each other. On a near match, comment on or amend the existing issue rather than promoting a duplicate. The bar for promoting to a bug: choose `type: bug` only when the reported behavior breaks an approved requirement or a defined acceptance criterion, and name which one. If you cannot name one, promote it as `task` \u2014 or leave it as feedback. A queue holding both real defects and unshared taste has to be read entirely before any of it can be trusted. Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Work of any kind carries criteria \u2014 an epic, a task, a bug \u2014 because what they answer is how anyone knows the thing is done, and that question does not get easier as the work gets smaller; feedback is the one exception, refused with `criteria_not_supported`, because it is a report rather than agreed work and `promote_feedback` retypes it into work before anything is built. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17106
17107
  inputSchema: {
17107
17108
  issue: external_exports.string().min(1),
17108
17109
  ...promoteFeedbackInputSchema.shape
17109
17110
  }
17110
17111
  }, ({ issue: issue2, ...fields }) => run(() => client2.promoteFeedback(issue2, fields)));
17111
17112
  registerTool("update_issue", {
17112
- description: 'Update any subset of an issue\u2019s title, body, type, priority, milestone, environment, parent (self/cycle rejected), requirement_links (add/remove; adding a link to an unapproved requirement is rejected), deliverable_links (add/remove content-deliverable links, add pins at the current revision), or decision_links (add/remove decision records this work sits under \u2014 `KEY-D{n}`, from `list_decisions`). Changing type away from epic is rejected while the epic has criteria (\xA77). Clearing `milestone` (passing null) is rejected while the issue sits past `triage` \u2014 work already scheduled keeps a milestone (PIPE-R10 rule 9); swap it for a different one, or move the issue back to `triage` first. Cite the decision record a piece of work implements rather than restating what was decided in its body: the record is where the reasoning stays correct, and a body repeating it goes stale the moment the decision is superseded. Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17113
+ description: 'Update any subset of an issue\u2019s title, body, type, priority, milestone, environment, parent (self/cycle rejected), requirement_links (add/remove; adding a link to an unapproved requirement is rejected), deliverable_links (add/remove content-deliverable links, add pins at the current revision), or decision_links (add/remove decision records this work sits under \u2014 `KEY-D{n}`, from `list_decisions`). Changing type to `feedback` is rejected while the issue has criteria (\xA77), since feedback carries none; epic, task and bug interchange freely and the criteria ride along, keeping their AC-{n} numbers and their states. Clearing `milestone` (passing null) is rejected while the issue sits past `triage` \u2014 work already scheduled keeps a milestone (PIPE-R10 rule 9); swap it for a different one, or move the issue back to `triage` first. Cite the decision record a piece of work implements rather than restating what was decided in its body: the record is where the reasoning stays correct, and a body repeating it goes stale the moment the decision is superseded. Link another record by key plus title on first mention; never paste its text into a body \u2014 the source changes, the copy does not, and a stale copy gets built. A decision you need from the operator is filed as a question via `ask_questions`, never written as an "Open questions" heading inside a body \u2014 a heading prompts nobody and records no answer, so a later session cannot tell whether the decision was made. Cross-cutting requirements bind every epic automatically and arrive with `get_issue` \u2014 never restate them in a body and never add them to `requirement_links`; an explicit link pins the linked document\u2019s approved revision.',
17113
17114
  inputSchema: updateIssueInputSchema.shape
17114
17115
  }, ({ issue: issue2, ...fields }) => run(() => client2.updateIssue(issue2, fields)));
17115
17116
  registerTool("set_status", {
17116
- description: "Set an issue\u2019s status; \xA76 epic guards apply and a guard failure returns the specific reason (verify needs every auto criterion passed; done needs every criterion passed; both need at least one criterion to exist, naming the unmet ones) (\xA77). A BLOCKED issue \u2014 one carrying an explicit mark or waiting on a blocker that is not yet `done`/`killed` \u2014 cannot move to `ready` or `in_progress`, and the refusal names the reason and every unresolved blocker, so clear the mark (`clear_blocked`) or finish, kill or `unlink_blocker` each blocker first; every other target still moves while blocked. An issue with NO milestone cannot move to any status but `triage` and `killed` (PIPE-R10 rule 9) \u2014 set one with `update_issue` first; `killed` is exempt, so work nobody scheduled can still be abandoned.",
17117
+ description: "Set an issue\u2019s status; the \xA76 guards apply and a guard failure returns the specific reason, naming the rows it refused on (\xA77). The criteria gates read whatever criteria the issue carries, whatever its type: verify needs every auto criterion passed, done needs every criterion passed. Two guards remain EPIC-ONLY, and the asymmetry is the rule rather than an oversight \u2014 an epic that has stated NO criteria is refused at both gates, because an empty list would clear them having committed to nothing, while a task or a bug carrying none moves through both untouched (most work is stated adequately by its body); and `done` on an epic additionally requires every child to be terminal, read from each child\u2019s STATUS and never from its criteria. A BLOCKED issue \u2014 one carrying an explicit mark or waiting on a blocker that is not yet `done`/`killed` \u2014 cannot move to `ready` or `in_progress`, and the refusal names the reason and every unresolved blocker, so clear the mark (`clear_blocked`) or finish, kill or `unlink_blocker` each blocker first; every other target still moves while blocked. An issue with NO milestone cannot move to any status but `triage` and `killed` (PIPE-R10 rule 9) \u2014 set one with `update_issue` first; `killed` is exempt, so work nobody scheduled can still be abandoned.",
17117
17118
  inputSchema: setStatusInputSchema.shape
17118
17119
  }, (args) => run(() => client2.setStatus(args.issue, args.status)));
17119
17120
  registerTool("claim_issue", {
@@ -17145,11 +17146,11 @@ Every loose end has one destination, and none of them is prose. Anything you not
17145
17146
  inputSchema: linkBlockerInputSchema.shape
17146
17147
  }, (args) => run(() => client2.removeBlocker(args.issue, args.blocker)));
17147
17148
  registerTool("set_criteria", {
17148
- description: "Epic only: define or replace the ordered acceptance criteria list ({text, verification, howTo}). Matched rows keep their stable AC-{n} number; new items get fresh never-reused numbers; removed items are soft-deleted. A matched row keeps its state only when BOTH its text and verification mode are unchanged \u2014 a mode flip resets it to pending (\xA77). Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Criteria live on epics only: a task cannot carry a criteria list and instead states in its own body what would count as done.",
17149
+ description: "Define or replace the ordered acceptance criteria list ({text, verification, howTo}) on a piece of work. Matched rows keep their stable AC-{n} number; new items get fresh never-reused numbers; removed items are soft-deleted. A matched row keeps its state only when BOTH its text and verification mode are unchanged \u2014 a mode flip resets it to pending (\xA77). Before assigning any verification mode, establish what this project can drive end to end \u2014 an end-to-end test harness and the command that runs it. A criterion is `auto` when an evaluator can drive the input and read the result against the running system, which includes behavior shown in the interface wherever such a harness exists; the mode follows from what can be driven, not from where the behavior appears. What qualifies a criterion as `auto` is the evaluator\u2019s own run, never the existence of a test the implementer wrote. Mark `manual` only when the verdict needs a person\u2019s judgment; a criterion you cannot describe as drivable is usually worded too vaguely, so reword it against the observable rather than fall back to a person. A `manual` criterion must also carry `howTo` \u2014 one or two sentences, not an essay, saying where to look, what to do, and what counts as passing for whoever checks it by hand. Writing or changing one without it is refused (`how_to_required`); so is supplying it on an `auto` criterion, which a machine checks. Work of any kind carries criteria \u2014 an epic, a task, a bug \u2014 because what they answer is how anyone knows the thing is done, and that question does not get easier as the work gets smaller; feedback is the one exception, refused with `criteria_not_supported`, because it is a report rather than agreed work and `promote_feedback` retypes it into work before anything is built. An evaluator RAISES a criterion from `manual` to `auto` only on a drive that actually succeeded \u2014 never on one it expects to succeed \u2014 and never lowers one. The flip both resets the state and clears the stored `howTo`, so a criterion moved to `auto` has lost its checking instructions \u2014 moving it back to `manual` does not restore them, and is refused (`how_to_required`) until you write new ones.",
17149
17150
  inputSchema: setCriteriaInputSchema.shape
17150
17151
  }, (args) => run(() => client2.setCriteria(args.issue, args.criteria)));
17151
17152
  registerTool("set_criterion_state", {
17152
- description: "Set a criterion\u2019s state (pending/passed/failed) on an epic, addressed by criterionId ALONE, or by issue + criterionNumber (the stable AC-{n}) \u2014 exactly one form. A token-authenticated call is REJECTED on a manual criterion (manual state is web-session-only, \xA74); evidence is required when a token marks passed/failed (\xA77).",
17153
+ description: "Set a criterion\u2019s state (pending/passed/failed) on whatever work carries it \u2014 an epic, a task and a bug alike \u2014 addressed by criterionId ALONE, or by issue + criterionNumber (the stable AC-{n}); exactly one form. Feedback never carries criteria, so neither address resolves to one. A token-authenticated call is REJECTED on a manual criterion (manual state is web-session-only, \xA74); evidence is required when a token marks passed/failed (\xA77).",
17153
17154
  // `issue` is OPTIONAL: the criterionId-only form needs no issue ref. The
17154
17155
  // exactly-one-of rule can't be expressed in a raw shape, so the handler
17155
17156
  // enforces it via the shared `@pipeline/domain` refine (mirror of §7).
@@ -17424,7 +17425,7 @@ function loadMcpConfig() {
17424
17425
  }
17425
17426
 
17426
17427
  // src/version.ts
17427
- var VERSION = "0.23.0";
17428
+ var VERSION = "0.25.0";
17428
17429
 
17429
17430
  // src/main.ts
17430
17431
  var config2 = loadMcpConfig();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipebrain-mcp",
3
- "version": "0.23.0",
3
+ "version": "0.25.0",
4
4
  "description": "Pipebrain MCP server for Claude Code and Claude Desktop — issues, requirements, content, assets, and metadata-only secrets over the Pipebrain API.",
5
5
  "type": "module",
6
6
  "license": "MIT",