@pantion/dialogs 0.2.1 → 0.3.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 (126) hide show
  1. package/dialogs/router/convergence-rules.md +160 -0
  2. package/dialogs/router/dialog.json +12 -0
  3. package/dialogs/router/translate.md +21 -0
  4. package/dialogs/software/convergence-rules.md +202 -15
  5. package/dialogs/software/prompts/convergence-intro.md +27 -15
  6. package/dist/core/feedback/aggregator.d.ts +7 -0
  7. package/dist/core/feedback/aggregator.d.ts.map +1 -0
  8. package/dist/core/feedback/aggregator.js +119 -0
  9. package/dist/core/feedback/aggregator.js.map +1 -0
  10. package/dist/core/feedback/store.d.ts +20 -0
  11. package/dist/core/feedback/store.d.ts.map +1 -0
  12. package/dist/core/feedback/store.js +111 -0
  13. package/dist/core/feedback/store.js.map +1 -0
  14. package/dist/core/feedback/suggestions.d.ts +5 -0
  15. package/dist/core/feedback/suggestions.d.ts.map +1 -0
  16. package/dist/core/feedback/suggestions.js +60 -0
  17. package/dist/core/feedback/suggestions.js.map +1 -0
  18. package/dist/core/feedback/types.d.ts +26 -0
  19. package/dist/core/feedback/types.d.ts.map +1 -0
  20. package/dist/core/feedback/types.js +2 -0
  21. package/dist/core/feedback/types.js.map +1 -0
  22. package/dist/core/index.d.ts +16 -3
  23. package/dist/core/index.d.ts.map +1 -1
  24. package/dist/core/index.js +10 -2
  25. package/dist/core/index.js.map +1 -1
  26. package/dist/core/protocol/loader.d.ts +4 -0
  27. package/dist/core/protocol/loader.d.ts.map +1 -1
  28. package/dist/core/protocol/loader.js +16 -0
  29. package/dist/core/protocol/loader.js.map +1 -1
  30. package/dist/core/protocol/stamp-parser.d.ts.map +1 -1
  31. package/dist/core/protocol/stamp-parser.js +2 -1
  32. package/dist/core/protocol/stamp-parser.js.map +1 -1
  33. package/dist/core/protocol/system-prompt.d.ts +17 -0
  34. package/dist/core/protocol/system-prompt.d.ts.map +1 -1
  35. package/dist/core/protocol/system-prompt.js +63 -5
  36. package/dist/core/protocol/system-prompt.js.map +1 -1
  37. package/dist/core/router/classifier.d.ts +29 -0
  38. package/dist/core/router/classifier.d.ts.map +1 -0
  39. package/dist/core/router/classifier.js +160 -0
  40. package/dist/core/router/classifier.js.map +1 -0
  41. package/dist/core/router/context.d.ts +28 -0
  42. package/dist/core/router/context.d.ts.map +1 -0
  43. package/dist/core/router/context.js +65 -0
  44. package/dist/core/router/context.js.map +1 -0
  45. package/dist/core/router/menu.d.ts +18 -0
  46. package/dist/core/router/menu.d.ts.map +1 -0
  47. package/dist/core/router/menu.js +109 -0
  48. package/dist/core/router/menu.js.map +1 -0
  49. package/dist/core/router/next-actions.d.ts +17 -0
  50. package/dist/core/router/next-actions.d.ts.map +1 -0
  51. package/dist/core/router/next-actions.js +153 -0
  52. package/dist/core/router/next-actions.js.map +1 -0
  53. package/dist/core/router/types.d.ts +49 -0
  54. package/dist/core/router/types.d.ts.map +1 -0
  55. package/dist/core/router/types.js +8 -0
  56. package/dist/core/router/types.js.map +1 -0
  57. package/dist/core/types.d.ts +2 -0
  58. package/dist/core/types.d.ts.map +1 -1
  59. package/dist/core/utils/datetime.d.ts +13 -0
  60. package/dist/core/utils/datetime.d.ts.map +1 -0
  61. package/dist/core/utils/datetime.js +17 -0
  62. package/dist/core/utils/datetime.js.map +1 -0
  63. package/dist/feature-set.d.ts.map +1 -1
  64. package/dist/feature-set.js +4 -0
  65. package/dist/feature-set.js.map +1 -1
  66. package/dist/index.js +3 -3
  67. package/dist/index.js.map +1 -1
  68. package/dist/prompts/workflow-prompts.d.ts.map +1 -1
  69. package/dist/prompts/workflow-prompts.js +81 -1
  70. package/dist/prompts/workflow-prompts.js.map +1 -1
  71. package/dist/server.d.ts.map +1 -1
  72. package/dist/server.js +6 -0
  73. package/dist/server.js.map +1 -1
  74. package/dist/tools/amend.d.ts.map +1 -1
  75. package/dist/tools/amend.js +2 -2
  76. package/dist/tools/amend.js.map +1 -1
  77. package/dist/tools/approve.d.ts.map +1 -1
  78. package/dist/tools/approve.js +2 -2
  79. package/dist/tools/approve.js.map +1 -1
  80. package/dist/tools/build.d.ts +4 -0
  81. package/dist/tools/build.d.ts.map +1 -0
  82. package/dist/tools/build.js +200 -0
  83. package/dist/tools/build.js.map +1 -0
  84. package/dist/tools/check-convergence.d.ts.map +1 -1
  85. package/dist/tools/check-convergence.js +15 -1
  86. package/dist/tools/check-convergence.js.map +1 -1
  87. package/dist/tools/feedback.d.ts +4 -0
  88. package/dist/tools/feedback.d.ts.map +1 -0
  89. package/dist/tools/feedback.js +51 -0
  90. package/dist/tools/feedback.js.map +1 -0
  91. package/dist/tools/index.d.ts.map +1 -1
  92. package/dist/tools/index.js +9 -1
  93. package/dist/tools/index.js.map +1 -1
  94. package/dist/tools/learn.d.ts +4 -0
  95. package/dist/tools/learn.d.ts.map +1 -0
  96. package/dist/tools/learn.js +38 -0
  97. package/dist/tools/learn.js.map +1 -0
  98. package/dist/tools/reflect.d.ts.map +1 -1
  99. package/dist/tools/reflect.js +68 -1
  100. package/dist/tools/reflect.js.map +1 -1
  101. package/dist/tools/reject.d.ts.map +1 -1
  102. package/dist/tools/reject.js +2 -2
  103. package/dist/tools/reject.js.map +1 -1
  104. package/dist/tools/router.d.ts +10 -0
  105. package/dist/tools/router.d.ts.map +1 -0
  106. package/dist/tools/router.js +315 -0
  107. package/dist/tools/router.js.map +1 -0
  108. package/dist/tools/save-canon.d.ts.map +1 -1
  109. package/dist/tools/save-canon.js +28 -12
  110. package/dist/tools/save-canon.js.map +1 -1
  111. package/dist/tools/start.d.ts.map +1 -1
  112. package/dist/tools/start.js +20 -7
  113. package/dist/tools/start.js.map +1 -1
  114. package/dist/tools/translate.d.ts.map +1 -1
  115. package/dist/tools/translate.js +21 -4
  116. package/dist/tools/translate.js.map +1 -1
  117. package/package.json +1 -1
  118. package/protocol/commands/dialog-post.md +46 -0
  119. package/protocol/commands/dialog-stamps.md +67 -0
  120. package/protocol/commands/dialog.md +4 -98
  121. package/protocol/commands/start-post.md +53 -0
  122. package/protocol/commands/start-stamps.md +133 -0
  123. package/protocol/commands/start.md +20 -167
  124. package/protocol/core-save.md +102 -0
  125. package/protocol/core-stamps.md +97 -0
  126. package/protocol/core.md +4 -191
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Intent classifier — keyword matching + confidence scoring.
3
+ *
4
+ * English-only keyword register. Non-English intents fall through
5
+ * to the LLM fallback zone (confidence < 0.75).
6
+ */
7
+ import type { RouterAction } from './types.js';
8
+ import type { CanonEntry, SessionMeta } from '../types.js';
9
+ export declare const KEYWORD_REGISTER: Record<RouterAction, string[]>;
10
+ export declare const HIGH_RISK_ACTIONS: ReadonlySet<RouterAction>;
11
+ /** Map RouterAction to MCP tool name */
12
+ export declare const ACTION_TO_TOOL: Record<RouterAction, string>;
13
+ export interface ClassificationContext {
14
+ canons?: CanonEntry[];
15
+ sessions?: SessionMeta[];
16
+ hasPatterns?: boolean;
17
+ }
18
+ export interface ClassificationResult {
19
+ action: RouterAction;
20
+ confidence: number;
21
+ confidence_reason: string;
22
+ decision_path: 'rules_only' | 'rules+context';
23
+ }
24
+ /**
25
+ * Classify user intent into a RouterAction using keyword matching + context.
26
+ * Returns null if no match found (confidence too low for deterministic routing).
27
+ */
28
+ export declare function classifyIntent(userIntent: string, context?: ClassificationContext): ClassificationResult | null;
29
+ //# sourceMappingURL=classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../../src/core/router/classifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,CAW3D,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,YAAY,CAA8C,CAAC;AAEvG,wCAAwC;AACxC,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAWvD,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,YAAY,GAAG,eAAe,CAAC;CAC/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,GAAG,IAAI,CA2D7B"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Intent classifier — keyword matching + confidence scoring.
3
+ *
4
+ * English-only keyword register. Non-English intents fall through
5
+ * to the LLM fallback zone (confidence < 0.75).
6
+ */
7
+ export const KEYWORD_REGISTER = {
8
+ start: ['start', 'new', 'create', 'build', 'make', 'begin', 'kickoff'],
9
+ resume: ['resume', 'continue', 'pick up', 'go on', 'carry on'],
10
+ amend: ['amend', 'change', 'modify', 'add', 'update', 'revise', 'tweak'],
11
+ check: ['check', 'validate', 'quality', 'ready', 'done', 'verify', 'health', 'complete'],
12
+ approve: ['approve', 'accept', 'authorize', 'sign off', 'ship', 'greenlight'],
13
+ translate: ['translate', 'generate', 'spec', 'files', 'write specs', 'generate requirements'],
14
+ reflect: ['reflect', 'reality', "didn't work", 'unexpected', 'retrospective', 'postmortem'],
15
+ feedback: ['feedback', 'missed', 'wrong', 'should have', 'missed question', 'should ask'],
16
+ learn: ['learn', 'patterns', 'aggregate', 'improve', 'insights', 'trends'],
17
+ list: ['list', 'show', 'overview', 'status', 'where', 'what do we have'],
18
+ };
19
+ export const HIGH_RISK_ACTIONS = new Set(['approve', 'translate', 'amend']);
20
+ /** Map RouterAction to MCP tool name */
21
+ export const ACTION_TO_TOOL = {
22
+ start: 'pantion_start',
23
+ resume: 'pantion_resume',
24
+ amend: 'pantion_amend',
25
+ check: 'pantion_check',
26
+ approve: 'pantion_approve',
27
+ translate: 'pantion_translate',
28
+ reflect: 'pantion_reflect',
29
+ feedback: 'pantion_feedback',
30
+ learn: 'pantion_learn',
31
+ list: 'pantion_list-canons',
32
+ };
33
+ /**
34
+ * Classify user intent into a RouterAction using keyword matching + context.
35
+ * Returns null if no match found (confidence too low for deterministic routing).
36
+ */
37
+ export function classifyIntent(userIntent, context) {
38
+ const normalized = userIntent.toLowerCase().trim();
39
+ if (!normalized)
40
+ return null;
41
+ // Phase 1: keyword matching — find best match
42
+ let bestAction = null;
43
+ let bestScore = 0;
44
+ let matchedKeyword = '';
45
+ for (const [action, keywords] of Object.entries(KEYWORD_REGISTER)) {
46
+ for (const keyword of keywords) {
47
+ if (normalized.includes(keyword)) {
48
+ // Prefer longer keyword matches (more specific)
49
+ const score = keyword.length;
50
+ if (score > bestScore) {
51
+ bestScore = score;
52
+ bestAction = action;
53
+ matchedKeyword = keyword;
54
+ }
55
+ }
56
+ }
57
+ }
58
+ if (!bestAction) {
59
+ // No keyword match at all
60
+ return null;
61
+ }
62
+ // Phase 2: context enrichment
63
+ let confidence = 0.9;
64
+ let confidence_reason = `Keyword match: "${matchedKeyword}"`;
65
+ let decision_path = 'rules_only';
66
+ if (context) {
67
+ const contextSignal = checkContextAlignment(bestAction, context);
68
+ decision_path = 'rules+context';
69
+ if (contextSignal === 'confirms') {
70
+ confidence = 0.95;
71
+ confidence_reason = `Keyword "${matchedKeyword}" + context confirms`;
72
+ }
73
+ else if (contextSignal === 'conflicts') {
74
+ confidence = 0.3;
75
+ confidence_reason = `Keyword "${matchedKeyword}" but context conflicts`;
76
+ }
77
+ // 'neutral' keeps 0.9
78
+ }
79
+ // Phase 3: multi-signal boost
80
+ if (confidence >= 0.9 && hasMultipleSignals(normalized, bestAction)) {
81
+ confidence = 0.97;
82
+ confidence_reason += ' + multi-signal boost';
83
+ }
84
+ return {
85
+ action: bestAction,
86
+ confidence,
87
+ confidence_reason,
88
+ decision_path,
89
+ };
90
+ }
91
+ function checkContextAlignment(action, context) {
92
+ const { canons, sessions } = context;
93
+ switch (action) {
94
+ case 'resume': {
95
+ const hasDrafts = canons?.some(c => c.status.toLowerCase().includes('draft'));
96
+ const hasActiveSessions = sessions && sessions.length > 0;
97
+ if (hasDrafts || hasActiveSessions)
98
+ return 'confirms';
99
+ if (canons && canons.length > 0 && !hasDrafts)
100
+ return 'conflicts';
101
+ return 'neutral';
102
+ }
103
+ case 'approve': {
104
+ const hasConvergedPending = canons?.some(c => c.status.toLowerCase().includes('converged') && c.humanStampStatus === 'PENDING');
105
+ if (hasConvergedPending)
106
+ return 'confirms';
107
+ if (canons && canons.length > 0 && !hasConvergedPending)
108
+ return 'conflicts';
109
+ return 'neutral';
110
+ }
111
+ case 'translate': {
112
+ const hasApproved = canons?.some(c => c.humanStampStatus === 'APPROVED' || c.humanStampStatus === 'AUTO-APPROVED');
113
+ if (hasApproved)
114
+ return 'confirms';
115
+ if (canons && canons.length > 0 && !hasApproved)
116
+ return 'conflicts';
117
+ return 'neutral';
118
+ }
119
+ case 'check': {
120
+ const hasCanons = canons && canons.length > 0;
121
+ if (hasCanons)
122
+ return 'confirms';
123
+ return 'neutral';
124
+ }
125
+ case 'amend': {
126
+ const hasConverged = canons?.some(c => c.status.toLowerCase().includes('converged'));
127
+ if (hasConverged)
128
+ return 'confirms';
129
+ if (canons && canons.length > 0 && !hasConverged)
130
+ return 'conflicts';
131
+ return 'neutral';
132
+ }
133
+ case 'learn': {
134
+ if (context.hasPatterns)
135
+ return 'confirms';
136
+ return 'neutral';
137
+ }
138
+ default:
139
+ return 'neutral';
140
+ }
141
+ }
142
+ /**
143
+ * Check for multi-signal boost: intent contains action keyword + object reference + temporal marker.
144
+ */
145
+ function hasMultipleSignals(normalized, action) {
146
+ // Object references (canon names, dialog types, etc.)
147
+ const objectPatterns = [
148
+ /(?:canon|project|dialog|software|image)\b/,
149
+ /["'][^"']+["']/,
150
+ ];
151
+ // Temporal markers
152
+ const temporalPatterns = [
153
+ /\b(?:now|next|first|then|after|before|today|please)\b/,
154
+ ];
155
+ const hasObject = objectPatterns.some(p => p.test(normalized));
156
+ const hasTemporal = temporalPatterns.some(p => p.test(normalized));
157
+ const hasKeyword = KEYWORD_REGISTER[action].some(k => normalized.includes(k));
158
+ return hasKeyword && hasObject && hasTemporal;
159
+ }
160
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../../src/core/router/classifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Context collector — layered context collection for the router.
3
+ *
4
+ * Always: readCanonIndex + listDialogs
5
+ * Conditional: readProjectPatterns (learn/feedback/start), listSessions (resume or low confidence)
6
+ */
7
+ import type { CanonEntry, SessionMeta } from '../types.js';
8
+ import type { RouterAction } from './types.js';
9
+ export interface DialogInfo {
10
+ name: string;
11
+ displayName: string;
12
+ description: string;
13
+ }
14
+ export interface RouterContext {
15
+ canons: CanonEntry[];
16
+ dialogs: DialogInfo[];
17
+ sessions?: SessionMeta[];
18
+ patterns?: string;
19
+ warnings: string[];
20
+ }
21
+ /**
22
+ * Collect context for routing decisions.
23
+ *
24
+ * Layer 1 (always): canons + dialogs
25
+ * Layer 2 (conditional): patterns (learn/feedback/start) + sessions (resume or low confidence)
26
+ */
27
+ export declare function collectContext(projectPath: string, dialogsDir: string, intent?: RouterAction | null, confidence?: number): RouterContext;
28
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/core/router/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAU,MAAM,aAAa,CAAC;AAKnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAUD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,YAAY,GAAG,IAAI,EAC5B,UAAU,CAAC,EAAE,MAAM,GAClB,aAAa,CA2Cf"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Context collector — layered context collection for the router.
3
+ *
4
+ * Always: readCanonIndex + listDialogs
5
+ * Conditional: readProjectPatterns (learn/feedback/start), listSessions (resume or low confidence)
6
+ */
7
+ import { readCanonIndex } from '../canon/index-manager.js';
8
+ import { listDialogs } from '../dialog/registry.js';
9
+ import { listSessions } from '../session/manager.js';
10
+ import { readProjectPatterns } from '../feedback/store.js';
11
+ function toDialogInfo(dialog) {
12
+ return {
13
+ name: dialog.manifest.name,
14
+ displayName: dialog.manifest.displayName,
15
+ description: dialog.manifest.description,
16
+ };
17
+ }
18
+ /**
19
+ * Collect context for routing decisions.
20
+ *
21
+ * Layer 1 (always): canons + dialogs
22
+ * Layer 2 (conditional): patterns (learn/feedback/start) + sessions (resume or low confidence)
23
+ */
24
+ export function collectContext(projectPath, dialogsDir, intent, confidence) {
25
+ const warnings = [];
26
+ // Layer 1: always
27
+ let canons = [];
28
+ let dialogs = [];
29
+ try {
30
+ canons = readCanonIndex(projectPath);
31
+ }
32
+ catch {
33
+ warnings.push('Failed to read canon index');
34
+ }
35
+ try {
36
+ dialogs = listDialogs(projectPath, dialogsDir).map(toDialogInfo);
37
+ }
38
+ catch {
39
+ warnings.push('Failed to list dialogs');
40
+ }
41
+ const ctx = { canons, dialogs, warnings };
42
+ // Layer 2: conditional
43
+ const needsPatterns = intent === 'learn' || intent === 'feedback' || intent === 'start';
44
+ const needsSessions = intent === 'resume' || (confidence !== undefined && confidence < 0.75);
45
+ if (needsPatterns) {
46
+ try {
47
+ const patterns = readProjectPatterns(projectPath);
48
+ if (patterns)
49
+ ctx.patterns = patterns;
50
+ }
51
+ catch {
52
+ warnings.push('Failed to read project patterns');
53
+ }
54
+ }
55
+ if (needsSessions) {
56
+ try {
57
+ ctx.sessions = listSessions(projectPath);
58
+ }
59
+ catch {
60
+ warnings.push('Failed to list sessions');
61
+ }
62
+ }
63
+ return ctx;
64
+ }
65
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/core/router/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAiB3D,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;QAC1B,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;QACxC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW;KACzC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,UAAkB,EAClB,MAA4B,EAC5B,UAAmB;IAEnB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,kBAAkB;IAClB,IAAI,MAAM,GAAiB,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAiB,EAAE,CAAC;IAE/B,IAAI,CAAC;QACH,MAAM,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,GAAG,GAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEzD,uBAAuB;IACvB,MAAM,aAAa,GAAG,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,OAAO,CAAC;IACxF,MAAM,aAAa,GAAG,MAAM,KAAK,QAAQ,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,UAAU,GAAG,IAAI,CAAC,CAAC;IAE7F,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;YAClD,IAAI,QAAQ;gBAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACxC,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,GAAG,CAAC,QAAQ,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Menu builder — dynamic context menu for empty-input router calls.
3
+ *
4
+ * Three sections: continue (drafts), create (dialogs), manage (check/list/learn).
5
+ * Max 7 items total, only relevant sections shown.
6
+ */
7
+ import type { MenuSection } from './types.js';
8
+ import type { RouterContext } from './context.js';
9
+ /**
10
+ * Build a context-driven menu from project state.
11
+ * Only includes sections with relevant items.
12
+ */
13
+ export declare function buildMenu(context: RouterContext): MenuSection[];
14
+ /**
15
+ * Build a short context summary for the response.
16
+ */
17
+ export declare function buildContextSummary(context: RouterContext): string;
18
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../src/core/router/menu.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAgC,MAAM,YAAY,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,EAAE,CAwF/D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAkBlE"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Menu builder — dynamic context menu for empty-input router calls.
3
+ *
4
+ * Three sections: continue (drafts), create (dialogs), manage (check/list/learn).
5
+ * Max 7 items total, only relevant sections shown.
6
+ */
7
+ const MAX_MENU_ITEMS = 7;
8
+ /**
9
+ * Build a context-driven menu from project state.
10
+ * Only includes sections with relevant items.
11
+ */
12
+ export function buildMenu(context) {
13
+ const sections = [];
14
+ let totalItems = 0;
15
+ // Section 1: continue — drafts and active sessions
16
+ const continueItems = [];
17
+ for (const canon of context.canons) {
18
+ if (canon.status.toLowerCase().includes('draft') && totalItems + continueItems.length < MAX_MENU_ITEMS) {
19
+ const oqCount = canon.openQuestions.length;
20
+ const oqLabel = oqCount > 0 ? `, ${oqCount} open questions` : '';
21
+ continueItems.push({
22
+ label: `Resume "${canon.name}" (DRAFT${oqLabel})`,
23
+ action: 'resume',
24
+ args: { canon_name: canon.name },
25
+ priority: 1,
26
+ });
27
+ }
28
+ }
29
+ // Note: pantion_resume currently accepts canon_name only (not session_id).
30
+ // Session context is therefore handled indirectly via draft canons.
31
+ // Keep sessions available for routing confidence, but do not emit
32
+ // non-executable menu actions.
33
+ if (continueItems.length > 0) {
34
+ sections.push({ id: 'continue', title: 'Continue', items: continueItems });
35
+ totalItems += continueItems.length;
36
+ }
37
+ // Section 2: create — available dialogs
38
+ const createItems = [];
39
+ for (const dialog of context.dialogs) {
40
+ if (totalItems + createItems.length >= MAX_MENU_ITEMS)
41
+ break;
42
+ createItems.push({
43
+ label: dialog.displayName,
44
+ action: 'start',
45
+ args: { dialog: dialog.name },
46
+ reason: dialog.description,
47
+ priority: 3,
48
+ });
49
+ }
50
+ if (createItems.length > 0) {
51
+ sections.push({ id: 'create', title: 'New', items: createItems });
52
+ totalItems += createItems.length;
53
+ }
54
+ // Section 3: manage — check/list/learn (only if canons or patterns exist)
55
+ const hasCanons = context.canons.length > 0;
56
+ const hasPatterns = !!context.patterns;
57
+ if (hasCanons || hasPatterns) {
58
+ const manageItems = [];
59
+ if (hasCanons && totalItems + manageItems.length < MAX_MENU_ITEMS) {
60
+ const firstCanon = context.canons[0];
61
+ manageItems.push({
62
+ label: 'Quality check',
63
+ action: 'check',
64
+ args: firstCanon ? { canon_name: firstCanon.name } : undefined,
65
+ priority: 4,
66
+ });
67
+ }
68
+ if (totalItems + manageItems.length < MAX_MENU_ITEMS) {
69
+ manageItems.push({
70
+ label: 'List canons',
71
+ action: 'list',
72
+ priority: 5,
73
+ });
74
+ }
75
+ if (hasPatterns && totalItems + manageItems.length < MAX_MENU_ITEMS) {
76
+ manageItems.push({
77
+ label: 'Learn from feedback',
78
+ action: 'learn',
79
+ priority: 6,
80
+ });
81
+ }
82
+ if (manageItems.length > 0) {
83
+ sections.push({ id: 'manage', title: 'Manage', items: manageItems });
84
+ }
85
+ }
86
+ return sections;
87
+ }
88
+ /**
89
+ * Build a short context summary for the response.
90
+ */
91
+ export function buildContextSummary(context) {
92
+ const parts = [];
93
+ const canonCount = context.canons.length;
94
+ const draftCount = context.canons.filter(c => c.status.toLowerCase().includes('draft')).length;
95
+ const convergedCount = context.canons.filter(c => c.status.toLowerCase().includes('converged')).length;
96
+ if (canonCount === 0) {
97
+ parts.push('No canons yet');
98
+ }
99
+ else {
100
+ parts.push(`${canonCount} canon${canonCount !== 1 ? 's' : ''}`);
101
+ if (draftCount > 0)
102
+ parts.push(`${draftCount} draft${draftCount !== 1 ? 's' : ''}`);
103
+ if (convergedCount > 0)
104
+ parts.push(`${convergedCount} converged`);
105
+ }
106
+ parts.push(`${context.dialogs.length} dialog${context.dialogs.length !== 1 ? 's' : ''} available`);
107
+ return parts.join(', ');
108
+ }
109
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../../src/core/router/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Next-actions engine — follow-up action suggestions.
3
+ *
4
+ * Static successors (baseline) + context-aware ranking.
5
+ * Only valid, executable actions. Max 3 items.
6
+ */
7
+ import type { RouterAction, RouterMenuItem } from './types.js';
8
+ import type { RouterContext } from './context.js';
9
+ /** Baseline follow-up actions per flow */
10
+ export declare const STATIC_SUCCESSORS: Record<RouterAction, RouterAction[]>;
11
+ /** Fallback mapping for disabled tools — all non-mutative */
12
+ export declare const TOOL_FALLBACKS: Record<string, RouterAction>;
13
+ /**
14
+ * Build up to 3 next actions based on static successors + context ranking.
15
+ */
16
+ export declare function buildNextActions(action: RouterAction, context: RouterContext): RouterMenuItem[];
17
+ //# sourceMappingURL=next-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-actions.d.ts","sourceRoot":"","sources":["../../../src/core/router/next-actions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlD,0CAA0C;AAC1C,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,YAAY,EAAE,CAWlE,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAKvD,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc,EAAE,CAuB/F"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * Next-actions engine — follow-up action suggestions.
3
+ *
4
+ * Static successors (baseline) + context-aware ranking.
5
+ * Only valid, executable actions. Max 3 items.
6
+ */
7
+ import { isToolEnabled } from '../../feature-set.js';
8
+ import { ACTION_TO_TOOL } from './classifier.js';
9
+ const MAX_NEXT_ACTIONS = 3;
10
+ /** Baseline follow-up actions per flow */
11
+ export const STATIC_SUCCESSORS = {
12
+ start: ['check'],
13
+ resume: ['check'],
14
+ amend: ['check', 'approve'],
15
+ check: ['approve', 'amend'],
16
+ approve: ['translate'],
17
+ translate: ['list'],
18
+ reflect: ['feedback', 'amend'],
19
+ feedback: ['learn'],
20
+ learn: ['start', 'list'],
21
+ list: ['start', 'check'],
22
+ };
23
+ /** Fallback mapping for disabled tools — all non-mutative */
24
+ export const TOOL_FALLBACKS = {
25
+ reflect: 'list',
26
+ feedback: 'list',
27
+ learn: 'list',
28
+ translate: 'check',
29
+ };
30
+ /**
31
+ * Build up to 3 next actions based on static successors + context ranking.
32
+ */
33
+ export function buildNextActions(action, context) {
34
+ const successors = STATIC_SUCCESSORS[action] ?? [];
35
+ const candidates = [];
36
+ for (const next of successors) {
37
+ const toolName = ACTION_TO_TOOL[next];
38
+ if (!toolName || !isToolEnabled(toolName))
39
+ continue;
40
+ // Status-gated: skip actions that don't make sense in current context
41
+ if (!isActionValid(next, context))
42
+ continue;
43
+ candidates.push({
44
+ label: actionLabel(next),
45
+ action: next,
46
+ args: argsForAction(next, context),
47
+ reason: actionReason(next, context),
48
+ priority: actionPriority(next, context),
49
+ });
50
+ }
51
+ // Sort by priority (lower = higher priority) and take max 3
52
+ candidates.sort((a, b) => (a.priority ?? 99) - (b.priority ?? 99));
53
+ return candidates.slice(0, MAX_NEXT_ACTIONS);
54
+ }
55
+ function argsForAction(action, context) {
56
+ switch (action) {
57
+ case 'start': {
58
+ const firstDialog = context.dialogs[0];
59
+ return firstDialog ? { dialog: firstDialog.name } : undefined;
60
+ }
61
+ case 'resume': {
62
+ const draft = context.canons.find((c) => c.status.toLowerCase().includes('draft'));
63
+ return draft ? { canon_name: draft.name } : undefined;
64
+ }
65
+ case 'check':
66
+ case 'approve':
67
+ case 'translate':
68
+ case 'amend':
69
+ case 'reflect':
70
+ case 'feedback': {
71
+ const firstCanon = context.canons[0];
72
+ return firstCanon ? { canon_name: firstCanon.name } : undefined;
73
+ }
74
+ default:
75
+ return undefined;
76
+ }
77
+ }
78
+ function isActionValid(action, context) {
79
+ const { canons } = context;
80
+ switch (action) {
81
+ case 'approve': {
82
+ // Only valid if there are converged canons with PENDING stamp
83
+ return canons.some(c => c.status.toLowerCase().includes('converged') && c.humanStampStatus === 'PENDING');
84
+ }
85
+ case 'translate': {
86
+ // Only valid if there are approved canons
87
+ return canons.some(c => c.humanStampStatus === 'APPROVED' || c.humanStampStatus === 'AUTO-APPROVED');
88
+ }
89
+ case 'amend': {
90
+ // Only valid if there are converged canons
91
+ return canons.some(c => c.status.toLowerCase().includes('converged'));
92
+ }
93
+ case 'check': {
94
+ return canons.length > 0;
95
+ }
96
+ case 'resume': {
97
+ return canons.some(c => c.status.toLowerCase().includes('draft'));
98
+ }
99
+ default:
100
+ return true;
101
+ }
102
+ }
103
+ function actionLabel(action) {
104
+ const labels = {
105
+ start: 'Start new dialog',
106
+ resume: 'Resume draft',
107
+ amend: 'Amend canon',
108
+ check: 'Run quality check',
109
+ approve: 'Approve canon',
110
+ translate: 'Generate spec files',
111
+ reflect: 'Reality check',
112
+ feedback: 'Submit feedback',
113
+ learn: 'Learn from feedback',
114
+ list: 'List canons',
115
+ };
116
+ return labels[action];
117
+ }
118
+ function actionReason(action, context) {
119
+ switch (action) {
120
+ case 'approve': {
121
+ const pending = context.canons.filter(c => c.status.toLowerCase().includes('converged') && c.humanStampStatus === 'PENDING');
122
+ return `${pending.length} canon${pending.length !== 1 ? 's' : ''} awaiting approval`;
123
+ }
124
+ case 'check':
125
+ return 'Verify canon quality before proceeding';
126
+ case 'translate':
127
+ return 'Generate project spec files from approved canon';
128
+ case 'amend':
129
+ return 'Modify existing converged canon';
130
+ case 'start':
131
+ return 'Begin a new convergence dialog';
132
+ case 'list':
133
+ return 'View project status';
134
+ default:
135
+ return '';
136
+ }
137
+ }
138
+ function actionPriority(action, context) {
139
+ // 1 = must-next, 2 = risk-reduction, 3 = momentum
140
+ switch (action) {
141
+ case 'approve': {
142
+ const hasPending = context.canons.some(c => c.status.toLowerCase().includes('converged') && c.humanStampStatus === 'PENDING');
143
+ return hasPending ? 1 : 3;
144
+ }
145
+ case 'check':
146
+ return 2;
147
+ case 'translate':
148
+ return 1;
149
+ default:
150
+ return 3;
151
+ }
152
+ }
153
+ //# sourceMappingURL=next-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-actions.js","sourceRoot":"","sources":["../../../src/core/router/next-actions.ts"],"names":[],"mappings":"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"}