spets 0.1.67 → 0.1.68

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/index.js +83 -43
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -930,8 +930,8 @@ function buildClarifyPrompt(params) {
930
930
  const parts = [];
931
931
  parts.push("# Clarify Phase");
932
932
  parts.push("");
933
- parts.push("Your task is to identify any questions that need user input before generating the document.");
934
- parts.push("Do NOT generate the document yet - only generate questions if needed.");
933
+ parts.push("Your task is to identify decisions that need user input before proceeding.");
934
+ parts.push("Do NOT generate the document yet - only identify decision points.");
935
935
  parts.push("");
936
936
  parts.push("## Task Information");
937
937
  parts.push("");
@@ -943,52 +943,63 @@ function buildClarifyPrompt(params) {
943
943
  parts.push("");
944
944
  parts.push(params.gatheredContext);
945
945
  parts.push("");
946
- const hasQAHistory = params.previousQA && params.previousQA.length > 0;
947
- if (hasQAHistory) {
948
- parts.push("## Previous Q&A");
946
+ const hasPreviousDecisions = params.previousDecisions && params.previousDecisions.length > 0;
947
+ if (hasPreviousDecisions) {
948
+ parts.push("## Previous Decisions");
949
949
  parts.push("");
950
- for (const entry of params.previousQA) {
951
- parts.push(`**Q:** ${entry.question.question}`);
952
- parts.push(`**A:** ${entry.answer.answer}`);
950
+ for (const entry of params.previousDecisions) {
951
+ const selectedOption = entry.decision.options.find((o) => o.id === entry.answer.selectedOptionId);
952
+ const label = entry.answer.selectedOptionId === "ai" ? `AI recommendation (${entry.decision.aiRecommendation?.optionId})` : selectedOption?.label || entry.answer.selectedOptionId;
953
+ parts.push(`**${entry.decision.decision}**: ${label}`);
954
+ if (entry.answer.customInput) {
955
+ parts.push(` Custom input: ${entry.answer.customInput}`);
956
+ }
953
957
  parts.push("");
954
958
  }
955
- parts.push("## Your Task");
956
- parts.push("");
957
- parts.push("For each Q&A above, judge if the question is resolved:");
958
- parts.push("- Clear answer \u2192 resolved, do NOT re-ask");
959
- parts.push('- "you decide" / "\uC54C\uC544\uC11C \uD574" \u2192 resolved, use your judgment');
960
- parts.push('- "give options" / "\uC635\uC158 \uC918" \u2192 NOT resolved, re-ask WITH concrete options');
961
- parts.push("- Confused / unclear \u2192 NOT resolved, re-ask simpler");
962
- parts.push("");
963
- parts.push("Only output questions that are NOT resolved. Do NOT ask new questions.");
959
+ parts.push("Based on these decisions, identify any remaining decision points.");
960
+ parts.push("Do NOT re-ask about decisions already made.");
964
961
  parts.push("");
965
962
  } else {
966
- parts.push("## Consider");
963
+ parts.push("## Your Task");
967
964
  parts.push("");
968
- parts.push("1. Is the task clear enough to proceed?");
969
- parts.push("2. Are there ambiguities that need user decision?");
965
+ parts.push("Identify decision points where:");
966
+ parts.push("1. Multiple valid approaches exist");
967
+ parts.push("2. User preference matters");
968
+ parts.push("3. Tradeoffs need to be considered");
970
969
  parts.push("");
971
970
  }
972
971
  parts.push("## Output Format");
973
972
  parts.push("");
974
- parts.push("Output a JSON object with questions array:");
973
+ parts.push("For each decision, provide options with descriptions and tradeoffs.");
974
+ parts.push('Always include "ai" as the last option with your recommendation.');
975
975
  parts.push("");
976
976
  parts.push("```json");
977
977
  parts.push("{");
978
- parts.push(' "questions": [');
978
+ parts.push(' "ready": false,');
979
+ parts.push(' "decisions": [');
979
980
  parts.push(" {");
980
- parts.push(' "id": "q1",');
981
- parts.push(' "question": "Your specific question?",');
982
- parts.push(' "context": "Why this matters for the document",');
983
- parts.push(' "options": ["Option A", "Option B"] // optional');
981
+ parts.push(' "id": "d1",');
982
+ parts.push(' "decision": "What needs to be decided",');
983
+ parts.push(' "why": "Why this decision matters",');
984
+ parts.push(' "options": [');
985
+ parts.push(' { "id": "opt1", "label": "Option A", "description": "...", "tradeoffs": "..." },');
986
+ parts.push(' { "id": "opt2", "label": "Option B", "description": "...", "tradeoffs": "..." },');
987
+ parts.push(' { "id": "ai", "label": "Let AI decide", "description": "AI chooses based on context", "recommendation": "opt1", "reason": "..." }');
988
+ parts.push(" ]");
984
989
  parts.push(" }");
985
990
  parts.push(" ]");
986
991
  parts.push("}");
987
992
  parts.push("```");
988
993
  parts.push("");
989
- parts.push('If no questions are needed, return: `{"questions": []}`');
994
+ parts.push("If all clear to proceed:");
995
+ parts.push("```json");
996
+ parts.push('{ "ready": true, "decisions": [], "summary": "How we will proceed" }');
997
+ parts.push("```");
990
998
  parts.push("");
991
- parts.push("**Important:** Output ONLY the JSON, no other text.");
999
+ parts.push("**Important:**");
1000
+ parts.push("- Output ONLY the JSON, no other text.");
1001
+ parts.push("- Every decision MUST have at least 2 concrete options with descriptions and tradeoffs.");
1002
+ parts.push('- Every decision MUST include "ai" option as the last choice.');
992
1003
  parts.push("");
993
1004
  return parts.join("\n");
994
1005
  }
@@ -1387,7 +1398,7 @@ var Orchestrator = class {
1387
1398
  };
1388
1399
  }
1389
1400
  /**
1390
- * Phase 2: Question generation
1401
+ * Phase 2: Decision identification
1391
1402
  */
1392
1403
  responsePhaseClarify(state) {
1393
1404
  const prompt = buildClarifyPrompt({
@@ -1395,7 +1406,9 @@ var Orchestrator = class {
1395
1406
  step: state.currentStep,
1396
1407
  description: state.description,
1397
1408
  gatheredContext: state.exploreOutput ? JSON.stringify(state.exploreOutput) : "",
1409
+ previousDecisions: state.decisionHistory,
1398
1410
  previousQA: state.qaHistory,
1411
+ // Legacy support
1399
1412
  cwd: this.cwd
1400
1413
  });
1401
1414
  return {
@@ -1406,7 +1419,9 @@ var Orchestrator = class {
1406
1419
  description: state.description,
1407
1420
  prompt,
1408
1421
  gatheredContext: state.exploreOutput ? JSON.stringify(state.exploreOutput) : "",
1422
+ previousDecisions: state.decisionHistory,
1409
1423
  previousQA: state.qaHistory,
1424
+ // Legacy support
1410
1425
  onComplete: `npx spets orchestrate clarify-done ${state.taskId}`
1411
1426
  };
1412
1427
  }
@@ -1510,7 +1525,7 @@ ${issues}`;
1510
1525
  };
1511
1526
  }
1512
1527
  /**
1513
- * Checkpoint: Questions need answers
1528
+ * Checkpoint: Decisions need user input
1514
1529
  */
1515
1530
  responseCheckpointClarify(state) {
1516
1531
  return {
@@ -1518,7 +1533,9 @@ ${issues}`;
1518
1533
  checkpoint: "clarify",
1519
1534
  taskId: state.taskId,
1520
1535
  step: state.currentStep,
1536
+ decisions: state.decisions || [],
1521
1537
  questions: state.questions || [],
1538
+ // Legacy support
1522
1539
  onComplete: `npx spets orchestrate clarified ${state.taskId} '<answers_json>'`
1523
1540
  };
1524
1541
  }
@@ -1614,11 +1631,34 @@ ${issues}`;
1614
1631
  return this.responsePhaseClarify(state);
1615
1632
  }
1616
1633
  /**
1617
- * Phase 2 complete: Questions generated (or none)
1618
- * If questions exist → checkpoint
1619
- * If no questions → move to execute phase with accumulated answers
1634
+ * Phase 2 complete: Decisions identified (or ready to proceed)
1635
+ * If decisions exist → checkpoint for user input
1636
+ * If ready → move to execute phase
1637
+ */
1638
+ cmdClarifyDone(taskId, clarifyOutput) {
1639
+ const state = this.loadState(taskId);
1640
+ if (!state) {
1641
+ return this.responseError(`No workflow found: ${taskId}`, taskId);
1642
+ }
1643
+ if (!clarifyOutput.ready && clarifyOutput.decisions.length > 0) {
1644
+ state.decisions = clarifyOutput.decisions;
1645
+ state.status = "clarify_pending";
1646
+ state.phase = "clarify";
1647
+ this.saveState(state);
1648
+ return this.responseCheckpointClarify(state);
1649
+ }
1650
+ state.answers = state.decisionHistory?.map((entry) => entry.answer);
1651
+ state.status = "phase_execute";
1652
+ state.phase = "execute";
1653
+ state.verifyAttempts = 0;
1654
+ this.saveState(state);
1655
+ return this.responsePhaseExecute(state);
1656
+ }
1657
+ /**
1658
+ * Legacy support: Questions-based clarify done
1659
+ * @deprecated Use decision-based cmdClarifyDone instead
1620
1660
  */
1621
- cmdClarifyDone(taskId, questions) {
1661
+ cmdClarifyDoneLegacy(taskId, questions) {
1622
1662
  const state = this.loadState(taskId);
1623
1663
  if (!state) {
1624
1664
  return this.responseError(`No workflow found: ${taskId}`, taskId);
@@ -1638,22 +1678,22 @@ ${issues}`;
1638
1678
  return this.responsePhaseExecute(state);
1639
1679
  }
1640
1680
  /**
1641
- * Human answered questions
1642
- * - Store Q&A in history
1643
- * - Loop back to clarify phase - AI will judge if answers resolved the questions
1681
+ * Human made decisions
1682
+ * - Store decisions in history
1683
+ * - Loop back to clarify phase to check for remaining decisions
1644
1684
  */
1645
1685
  cmdClarified(taskId, answers) {
1646
1686
  const state = this.loadState(taskId);
1647
1687
  if (!state) {
1648
1688
  return this.responseError(`No workflow found: ${taskId}`, taskId);
1649
1689
  }
1650
- const questions = state.questions || [];
1651
- const newEntries = questions.map((q, i) => ({
1652
- question: q,
1653
- answer: answers[i] || { questionId: q.id, answer: "" }
1690
+ const decisions = state.decisions || [];
1691
+ const newEntries = decisions.map((d, i) => ({
1692
+ decision: d,
1693
+ answer: answers[i] || { decisionId: d.id, selectedOptionId: "ai" }
1654
1694
  }));
1655
- state.qaHistory = [...state.qaHistory || [], ...newEntries];
1656
- state.questions = void 0;
1695
+ state.decisionHistory = [...state.decisionHistory || [], ...newEntries];
1696
+ state.decisions = void 0;
1657
1697
  state.answers = void 0;
1658
1698
  state.status = "phase_clarify";
1659
1699
  state.phase = "clarify";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spets",
3
- "version": "0.1.67",
3
+ "version": "0.1.68",
4
4
  "description": "Spec Driven Development Execution Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",