@papi-ai/server 0.7.78 → 0.7.79

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/prompts.js CHANGED
@@ -13,6 +13,19 @@ If a candidate AD body could be invalidated by running a SQL query, refreshing a
13
13
  **Negative example (reject):** "External user feedback is now flowing. Stonebridge Systems is actively building." \u2014 this is a fact about the current state of the world. Capture as dogfood/signal observation; do not mint.
14
14
 
15
15
  This rule applies to: new ADs proposed during planning (Step 9), strategy review AD updates (section 5), and strategy_change AD updates. If you find an existing AD that violates this rule during housekeeping, propose deleting it (action: "delete") with a one-line rationale.`;
16
+ var AD_CONFLICT_SURFACING_RULES = `**A contradiction is NOT a veto \u2014 surface it, never silently shelve it.**
17
+
18
+ Active Decisions are *active*: they can be superseded, modified, or abandoned. You do NOT have authority to kill a piece of work simply because it cuts against one. That is the user's call, and they can only make it if you show it to them.
19
+
20
+ **Never do any of these to a task solely because it contradicts, competes with, or duplicates the intent of an existing AD:** cancel it; drop it to P3; defer it silently; omit it from the cycle without comment; or reduce its scope down to the part that fits the AD.
21
+
22
+ **Instead, emit a \`decisionConflicts\` entry** for it (see the structured-output schema) with: the task, the AD it collides with, one line on what the AD says versus what the task implies, 2-3 concrete options, and your recommendation. Also render a \`## Decisions Needed\` section in Part 1 listing the same, immediately before the BUILD HANDOFFs.
23
+
24
+ Apply will park each conflicted task as **Blocked** with a \`decision-gate\` blocker pointing at that AD. It clears automatically the moment the AD is resolved, confirmed, validated, or superseded \u2014 so the work returns to the board on its own once the user has decided. The task is preserved, not killed.
25
+
26
+ **Emit a conflict ONLY when the AD is the reason the work would not otherwise proceed.** If the task is fine to schedule, schedule it. If it is genuinely obsolete, duplicated, or already shipped, cancel it on THOSE grounds and say so \u2014 that is not an AD conflict. Do not manufacture conflicts to look thorough; a plan with zero real conflicts should emit an empty array.
27
+
28
+ This applies equally to *competing* work: two tasks proposing rival approaches to the same problem is a decision for the user, not a coin-flip for you.`;
16
29
  var OUTPUT_QUALITY_RUBRIC = `Quality bar \u2014 before emitting, self-score the artifact 1-10 on five dimensions: (1) **Clarity** \u2014 could a third LLM act on it with no extra context? (2) **Scope tightness** \u2014 one focused unit of work, not three bundled together. (3) **Specificity** \u2014 it names concrete files/paths/tasks/ADs, not vague references like "the auth module". (4) **Dependency surfacing** \u2014 prerequisite or upstream items are called out explicitly. (5) **Success-criteria concreteness** \u2014 "done" is testable and observable, not "looks good". Sum to /50. If any single dimension scores \u22644, or the total is <35, revise the artifact and re-score before emitting \u2014 do not ship a below-threshold artifact. This is a self-check gate, not an output field: do NOT add the scores to the artifact or the structured JSON.`;
17
30
  var PLAN_SYSTEM = `You are the PAPI Cycle Planner \u2014 an autonomous planning engine for software projects.
18
31
  You receive project context and produce a planning cycle output with a BUILD HANDOFF.
@@ -93,7 +106,8 @@ After your natural language output, include this EXACT format on its own line:
93
106
  "newTasks": [],
94
107
  "boardCorrections": [],
95
108
  "productBrief": null,
96
- "activeDecisions": []
109
+ "activeDecisions": [],
110
+ "decisionConflicts": [{"taskId": "string \u2014 an existing task ID or a newTasks tempId", "adId": "string \u2014 AD-N this collides with", "conflict": "string \u2014 one line: what the AD says vs what this task implies", "options": ["string \u2014 concrete option, e.g. 'Supersede AD-12 and schedule the task'"], "recommendation": "string \u2014 which option you would take and why, in one sentence"}]
97
111
  }
98
112
  \`\`\`
99
113
 
@@ -130,6 +144,7 @@ Everything in Part 1 (natural language) is **display-only**. Part 2 (structured
130
144
  - Updated or created Active Decisions in Part 1? \u2192 Put them in \`activeDecisions\` array (with id and full body including ### heading)
131
145
  - Found board corrections (wrong priority, missing fields, stale status) in Part 1? \u2192 Put them in \`boardCorrections\` array
132
146
  - Generated BUILD HANDOFFs in Part 1? \u2192 Put them in \`cycleHandoffs\` array
147
+ - Wrote a \`## Decisions Needed\` section in Part 1? \u2192 Put every entry in \`decisionConflicts\`. Nothing in that array means the user is never asked, and the work is lost. Omit the array (or leave it empty) when there are genuinely no AD conflicts.
133
148
  - **\`complexity\` uses the LONG forms only** \u2014 "XS", "Small", "Medium", "Large", "XL". Do NOT reuse the handoff EFFORT short-forms (S/M/L) for task complexity.
134
149
 
135
150
  **Example with populated fields (DO NOT copy literally \u2014 adapt to your actual analysis):**
@@ -317,7 +332,7 @@ Standard planning cycle with full board review.
317
332
  **\u26A0\uFE0F PRIORITY RECALIBRATION \u2014 do NOT rubber-stamp the submitted priority.** The priority set at idea submission reflects the submitter's view at that time, which may be outdated by the time the planner runs. For EVERY unreviewed task, evaluate its priority FROM SCRATCH against: (a) current horizon/stage/phase goals, (b) recent Active Decision changes, (c) recently shipped functionality that makes this task more or less urgent. If your assessed priority differs from the submitted one, set the new priority in \`boardCorrections\` and include the change in a **Priority Recalibration** paragraph in your cycle log (Step 8): list each changed task by ID, old priority \u2192 new priority, and a 1-sentence rationale. This paragraph is how the user sees what the planner recalibrated and why. If no priorities changed during triage, omit the paragraph.
318
333
  Also set complexity using the full range \u2014 **XS, Small, Medium, Large, XL** \u2014 based on actual scope, not conservatively. XS = single-line or config change. Small = one file, < 50 lines. Medium = 2-5 files. Large = cross-module, multiple components. XL = architectural, multi-day.
319
334
  **Module classification for cross-cutting tasks:** When a task title contains "audit"/"unfiltered"/"scoping"/"leak" plus a database-entity name (e.g. "audit ... cycle_learnings reads", "unfiltered cycle_tasks queries"), classify the module by the actual code surface that reads/writes the entity \u2014 not by the tool names mentioned in the title. The reasoning surface (e.g. "health" or "strategy_review") is often unrelated to the data-access surface. Resolve this by treating the entity name as the routing signal: tasks touching dashboard read/write paths belong to the Dashboard module even if the title mentions an MCP tool. Misclassification routes the task to the wrong shared cycle branch and surfaces the wrong MODULE INSTRUCTIONS to the builder.
320
- If a task is clearly obsolete, duplicated, or rejected, set its status to "Cancelled" with a \`closureReason\` explaining why.
335
+ If a task is clearly obsolete, duplicated, or rejected, set its status to "Cancelled" with a \`closureReason\` explaining why. **"It contradicts an Active Decision" is NOT one of those reasons** \u2014 route it to \`decisionConflicts\` instead (see the AD Conflict Surfacing rule below step 7).
321
336
  **\u2192 PERSIST:** For each task you set reviewed: true, corrected fields on, or marked "Cancelled", include it in \`boardCorrections\` in Part 2.
322
337
 
323
338
  3. **Board Integrity** \u2014 All tasks have complete fields? Priority still accurate? Duplicates? Stale In Progress tasks?
@@ -360,6 +375,10 @@ Standard planning cycle with full board review.
360
375
  **Epic-aware batching:** Epic is the primary grouping signal for theme coherence. When multiple candidate tasks share the same epic (e.g. "Onboarding Redesign", "Dashboard Polish"), prefer co-scheduling them \u2014 they solve connected problems and benefit from shared context during the build. Steps: (1) After filtering by priority, group eligible tasks by epic. (2) If an epic has 3+ eligible tasks, prefer scheduling 2-4 of them together over cherry-picking across epics. (3) Report the epic distribution in the cycle log (e.g. "4 tasks from Onboarding epic, 1 from Platform"). Priority still overrides: a P0 fix from a different epic always takes precedence.
361
376
  **Opportunity clustering:** If backlog tasks have an \`opportunity\` field populated, group them by opportunity before selecting. Tasks sharing the same opportunity solve the same user problem \u2014 co-scheduling them produces more coherent cycles. Report opportunity clusters in the cycle log when present (e.g. "3 tasks clustered under 'planner accuracy' opportunity").
362
377
 
378
+ ${AD_CONFLICT_SURFACING_RULES}
379
+
380
+ **Where this fires:** during Inbox Triage (step 2), the Priority Drift Check (step 3), and selection (step 7). A task whose notes already carry an \`AD-CONFLICT:\` line, or an "AD-N alignment/conflict candidate" note from the idea tool, is a mandatory candidate \u2014 read it, and either schedule it, cancel it on non-AD grounds, or emit the conflict. Do not leave it sitting silently in Backlog for a third cycle.
381
+
363
382
  8. **Cycle Log** \u2014 Write 5-10 line entry: what was triaged, what was recommended and why, observations, AD updates. Include a **Priority Recalibration** paragraph if any unreviewed task priorities were changed during triage (Step 2) \u2014 list each by ID with old \u2192 new priority and rationale. Include a **Priority Drift Suggestions** paragraph if reviewed task drift was detected (Step 3).
364
383
  **Cycle Notes** \u2014 Optionally include 1-3 lines of cycle-level observations in \`cycleLogNotes\`: estimation accuracy patterns, recurring blockers, velocity trends, or dependency signals. These notes persist across cycles so future planning runs can learn from them. Use null if there are no noteworthy observations this cycle.
365
384
 
@@ -809,6 +828,13 @@ function coerceStructuredOutput(parsed) {
809
828
  })) : [];
810
829
  const cycleTaskIds = Array.isArray(parsed.cycleTaskIds) ? parsed.cycleTaskIds.map((id) => coerceToString(id)) : void 0;
811
830
  const carryForward = coerceCarryForward(parsed.cycleLogCarryForward);
831
+ const decisionConflicts = Array.isArray(parsed.decisionConflicts) ? parsed.decisionConflicts.map((c) => ({
832
+ taskId: coerceToString(c.taskId).trim(),
833
+ adId: coerceToString(c.adId).trim(),
834
+ conflict: coerceToString(c.conflict).trim(),
835
+ options: Array.isArray(c.options) ? c.options.map((o) => coerceToString(o)) : [],
836
+ recommendation: coerceToString(c.recommendation).trim()
837
+ })).filter((c) => c.taskId.length > 0 && c.adId.length > 0) : void 0;
812
838
  return {
813
839
  cycleLogTitle: coerceToString(parsed.cycleLogTitle),
814
840
  cycleLogContent: coerceToString(parsed.cycleLogContent),
@@ -824,7 +850,8 @@ function coerceStructuredOutput(parsed) {
824
850
  newTasks,
825
851
  boardCorrections,
826
852
  productBrief: parsed.productBrief === null ? null : coerceToString(parsed.productBrief),
827
- activeDecisions
853
+ activeDecisions,
854
+ decisionConflicts
828
855
  };
829
856
  }
830
857
  var REVIEW_SYSTEM_COMPRESSION_SECTION = `
@@ -899,6 +926,7 @@ You MUST cover these 5 sections. Each is mandatory.
899
926
  - Only flag ADs that represent a genuine strategic question requiring owner input
900
927
  - Note any hierarchy/phase issues worth correcting (1-2 bullets max)
901
928
  - Delete ADs that are legacy, process-level, or redundant without discussion
929
+ - **Blocked-on-decision tasks are evidence (task-3219).** If the board carries tasks Blocked behind a \`decision-gate\` on an AD, that AD is actively costing the project work. Resolve it here \u2014 supersede, modify, or explicitly reaffirm it with a one-line reason. Reaffirming is a legitimate answer; leaving it unaddressed is not, because the blocked work stays parked until someone rules.
902
930
 
903
931
  ${AD_REJECTION_RULES}
904
932
 
@@ -1667,6 +1695,7 @@ ${inputs.codebaseContext}
1667
1695
  Return a JSON array of 3-10 tasks based on gaps, improvements, and next steps visible from the codebase analysis above.`;
1668
1696
  }
1669
1697
  export {
1698
+ AD_CONFLICT_SURFACING_RULES,
1670
1699
  AD_REJECTION_RULES,
1671
1700
  AD_SEED_SYSTEM,
1672
1701
  CONVENTIONS_SYSTEM,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@papi-ai/server",
3
- "version": "0.7.78",
3
+ "version": "0.7.79",
4
4
  "description": "PAPI MCP server — AI-powered sprint planning, build execution, and strategy review for software projects",
5
5
  "license": "Elastic-2.0",
6
6
  "mcpName": "io.github.getpapi/papi",
@@ -22,6 +22,7 @@ Active Decisions (ADs) track architectural and product choices with confidence l
22
22
  - ADs are for product/architecture choices only, not process preferences.
23
23
  - When new evidence appears, update AD confidence via `strategy_change`.
24
24
  - Supersede rather than overwrite — old decisions stay as history.
25
+ - **A contradiction is not a veto.** If an idea or task cuts against a live AD, that is a decision for the user — never your reason to drop it. Submit it with `idea` + `conflicts_with_ad: "AD-N"`: the task is created and parked behind a decision gate, surfaces in `orient` as waiting on the owner, and returns to the board on its own once the AD is superseded, modified, or reaffirmed. Shelving the work instead means the AD never gets tested by the evidence that would have challenged it.
25
26
  - New ADs should include a `### Reversal Trigger` section: specify the signal that would invalidate the stance, the action to take (modify/supersede/abandon), and why writing it now prevents sunk-cost drift later.
26
27
 
27
28