@pantion/dialogs 0.2.1

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 (260) hide show
  1. package/dialogs/dialog-builder/convergence-rules.md +64 -0
  2. package/dialogs/dialog-builder/dialog.json +10 -0
  3. package/dialogs/dialog-builder/prompts/convergence-intro.md +21 -0
  4. package/dialogs/dialog-builder/prompts/translate-intro.md +17 -0
  5. package/dialogs/dialog-builder/translate.md +46 -0
  6. package/dialogs/image/convergence-rules.md +55 -0
  7. package/dialogs/image/dialog.json +12 -0
  8. package/dialogs/image/prompts/convergence-intro.md +25 -0
  9. package/dialogs/image/prompts/translate-intro.md +37 -0
  10. package/dialogs/image/translate.md +67 -0
  11. package/dialogs/software/convergence-rules.md +29 -0
  12. package/dialogs/software/dialog.json +12 -0
  13. package/dialogs/software/prompts/convergence-intro.md +22 -0
  14. package/dialogs/software/prompts/translate-intro.md +19 -0
  15. package/dialogs/software/translate.md +74 -0
  16. package/dialogs/software-brownfield/convergence-rules.md +109 -0
  17. package/dialogs/software-brownfield/dialog.json +12 -0
  18. package/dialogs/software-brownfield/prompts/convergence-intro.md +26 -0
  19. package/dialogs/software-brownfield/prompts/translate-intro.md +13 -0
  20. package/dialogs/software-brownfield/translate.md +56 -0
  21. package/dialogs/video/convergence-rules.md +96 -0
  22. package/dialogs/video/dialog.json +12 -0
  23. package/dialogs/video/prompts/convergence-intro.md +28 -0
  24. package/dialogs/video/prompts/translate-intro.md +41 -0
  25. package/dialogs/video/translate.md +81 -0
  26. package/dist/core/canon/index-manager.d.ts +27 -0
  27. package/dist/core/canon/index-manager.d.ts.map +1 -0
  28. package/dist/core/canon/index-manager.js +127 -0
  29. package/dist/core/canon/index-manager.js.map +1 -0
  30. package/dist/core/canon/manifest.d.ts +21 -0
  31. package/dist/core/canon/manifest.d.ts.map +1 -0
  32. package/dist/core/canon/manifest.js +56 -0
  33. package/dist/core/canon/manifest.js.map +1 -0
  34. package/dist/core/canon/validator.d.ts +12 -0
  35. package/dist/core/canon/validator.d.ts.map +1 -0
  36. package/dist/core/canon/validator.js +320 -0
  37. package/dist/core/canon/validator.js.map +1 -0
  38. package/dist/core/dialog/canon-writer.d.ts +22 -0
  39. package/dist/core/dialog/canon-writer.d.ts.map +1 -0
  40. package/dist/core/dialog/canon-writer.js +96 -0
  41. package/dist/core/dialog/canon-writer.js.map +1 -0
  42. package/dist/core/dialog/registry.d.ts +10 -0
  43. package/dist/core/dialog/registry.d.ts.map +1 -0
  44. package/dist/core/dialog/registry.js +102 -0
  45. package/dist/core/dialog/registry.js.map +1 -0
  46. package/dist/core/dialog/selector.d.ts +11 -0
  47. package/dist/core/dialog/selector.d.ts.map +1 -0
  48. package/dist/core/dialog/selector.js +32 -0
  49. package/dist/core/dialog/selector.js.map +1 -0
  50. package/dist/core/index.d.ts +20 -0
  51. package/dist/core/index.d.ts.map +1 -0
  52. package/dist/core/index.js +30 -0
  53. package/dist/core/index.js.map +1 -0
  54. package/dist/core/protocol/convergence.d.ts +11 -0
  55. package/dist/core/protocol/convergence.d.ts.map +1 -0
  56. package/dist/core/protocol/convergence.js +30 -0
  57. package/dist/core/protocol/convergence.js.map +1 -0
  58. package/dist/core/protocol/loader.d.ts +6 -0
  59. package/dist/core/protocol/loader.d.ts.map +1 -0
  60. package/dist/core/protocol/loader.js +31 -0
  61. package/dist/core/protocol/loader.js.map +1 -0
  62. package/dist/core/protocol/stamp-parser.d.ts +46 -0
  63. package/dist/core/protocol/stamp-parser.d.ts.map +1 -0
  64. package/dist/core/protocol/stamp-parser.js +333 -0
  65. package/dist/core/protocol/stamp-parser.js.map +1 -0
  66. package/dist/core/protocol/system-prompt.d.ts +16 -0
  67. package/dist/core/protocol/system-prompt.d.ts.map +1 -0
  68. package/dist/core/protocol/system-prompt.js +68 -0
  69. package/dist/core/protocol/system-prompt.js.map +1 -0
  70. package/dist/core/session/canon-writer.d.ts +33 -0
  71. package/dist/core/session/canon-writer.d.ts.map +1 -0
  72. package/dist/core/session/canon-writer.js +152 -0
  73. package/dist/core/session/canon-writer.js.map +1 -0
  74. package/dist/core/session/manager.d.ts +10 -0
  75. package/dist/core/session/manager.d.ts.map +1 -0
  76. package/dist/core/session/manager.js +105 -0
  77. package/dist/core/session/manager.js.map +1 -0
  78. package/dist/core/skill/canon-writer.d.ts +22 -0
  79. package/dist/core/skill/canon-writer.d.ts.map +1 -0
  80. package/dist/core/skill/canon-writer.js +96 -0
  81. package/dist/core/skill/canon-writer.js.map +1 -0
  82. package/dist/core/skill/registry.d.ts +10 -0
  83. package/dist/core/skill/registry.d.ts.map +1 -0
  84. package/dist/core/skill/registry.js +102 -0
  85. package/dist/core/skill/registry.js.map +1 -0
  86. package/dist/core/skill/selector.d.ts +11 -0
  87. package/dist/core/skill/selector.d.ts.map +1 -0
  88. package/dist/core/skill/selector.js +32 -0
  89. package/dist/core/skill/selector.js.map +1 -0
  90. package/dist/core/soul/registry.d.ts +10 -0
  91. package/dist/core/soul/registry.d.ts.map +1 -0
  92. package/dist/core/soul/registry.js +73 -0
  93. package/dist/core/soul/registry.js.map +1 -0
  94. package/dist/core/types.d.ts +154 -0
  95. package/dist/core/types.d.ts.map +1 -0
  96. package/dist/core/types.js +6 -0
  97. package/dist/core/types.js.map +1 -0
  98. package/dist/core/utils/fs.d.ts +14 -0
  99. package/dist/core/utils/fs.d.ts.map +1 -0
  100. package/dist/core/utils/fs.js +44 -0
  101. package/dist/core/utils/fs.js.map +1 -0
  102. package/dist/core/utils/project-detect.d.ts +3 -0
  103. package/dist/core/utils/project-detect.d.ts.map +1 -0
  104. package/dist/core/utils/project-detect.js +38 -0
  105. package/dist/core/utils/project-detect.js.map +1 -0
  106. package/dist/feature-set.d.ts +14 -0
  107. package/dist/feature-set.d.ts.map +1 -0
  108. package/dist/feature-set.js +38 -0
  109. package/dist/feature-set.js.map +1 -0
  110. package/dist/index.d.ts +3 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +56 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/prompts/convergence-prompts.d.ts +4 -0
  115. package/dist/prompts/convergence-prompts.d.ts.map +1 -0
  116. package/dist/prompts/convergence-prompts.js +76 -0
  117. package/dist/prompts/convergence-prompts.js.map +1 -0
  118. package/dist/prompts/index.d.ts +4 -0
  119. package/dist/prompts/index.d.ts.map +1 -0
  120. package/dist/prompts/index.js +7 -0
  121. package/dist/prompts/index.js.map +1 -0
  122. package/dist/prompts/workflow-prompts.d.ts +9 -0
  123. package/dist/prompts/workflow-prompts.d.ts.map +1 -0
  124. package/dist/prompts/workflow-prompts.js +265 -0
  125. package/dist/prompts/workflow-prompts.js.map +1 -0
  126. package/dist/resources/canon-resources.d.ts +4 -0
  127. package/dist/resources/canon-resources.d.ts.map +1 -0
  128. package/dist/resources/canon-resources.js +164 -0
  129. package/dist/resources/canon-resources.js.map +1 -0
  130. package/dist/server.d.ts +9 -0
  131. package/dist/server.d.ts.map +1 -0
  132. package/dist/server.js +47 -0
  133. package/dist/server.js.map +1 -0
  134. package/dist/tools/amend.d.ts +4 -0
  135. package/dist/tools/amend.d.ts.map +1 -0
  136. package/dist/tools/amend.js +106 -0
  137. package/dist/tools/amend.js.map +1 -0
  138. package/dist/tools/approve.d.ts +4 -0
  139. package/dist/tools/approve.d.ts.map +1 -0
  140. package/dist/tools/approve.js +60 -0
  141. package/dist/tools/approve.js.map +1 -0
  142. package/dist/tools/check-convergence.d.ts +4 -0
  143. package/dist/tools/check-convergence.d.ts.map +1 -0
  144. package/dist/tools/check-convergence.js +50 -0
  145. package/dist/tools/check-convergence.js.map +1 -0
  146. package/dist/tools/check.d.ts +4 -0
  147. package/dist/tools/check.d.ts.map +1 -0
  148. package/dist/tools/check.js +190 -0
  149. package/dist/tools/check.js.map +1 -0
  150. package/dist/tools/create-dialog.d.ts +4 -0
  151. package/dist/tools/create-dialog.d.ts.map +1 -0
  152. package/dist/tools/create-dialog.js +58 -0
  153. package/dist/tools/create-dialog.js.map +1 -0
  154. package/dist/tools/create-skill.d.ts +4 -0
  155. package/dist/tools/create-skill.d.ts.map +1 -0
  156. package/dist/tools/create-skill.js +58 -0
  157. package/dist/tools/create-skill.js.map +1 -0
  158. package/dist/tools/decompose.d.ts +4 -0
  159. package/dist/tools/decompose.d.ts.map +1 -0
  160. package/dist/tools/decompose.js +56 -0
  161. package/dist/tools/decompose.js.map +1 -0
  162. package/dist/tools/index.d.ts +4 -0
  163. package/dist/tools/index.d.ts.map +1 -0
  164. package/dist/tools/index.js +49 -0
  165. package/dist/tools/index.js.map +1 -0
  166. package/dist/tools/list-canons.d.ts +4 -0
  167. package/dist/tools/list-canons.d.ts.map +1 -0
  168. package/dist/tools/list-canons.js +28 -0
  169. package/dist/tools/list-canons.js.map +1 -0
  170. package/dist/tools/migrate.d.ts +4 -0
  171. package/dist/tools/migrate.d.ts.map +1 -0
  172. package/dist/tools/migrate.js +38 -0
  173. package/dist/tools/migrate.js.map +1 -0
  174. package/dist/tools/onboard.d.ts +4 -0
  175. package/dist/tools/onboard.d.ts.map +1 -0
  176. package/dist/tools/onboard.js +27 -0
  177. package/dist/tools/onboard.js.map +1 -0
  178. package/dist/tools/reconverge.d.ts +4 -0
  179. package/dist/tools/reconverge.d.ts.map +1 -0
  180. package/dist/tools/reconverge.js +68 -0
  181. package/dist/tools/reconverge.js.map +1 -0
  182. package/dist/tools/redialog.d.ts +4 -0
  183. package/dist/tools/redialog.d.ts.map +1 -0
  184. package/dist/tools/redialog.js +63 -0
  185. package/dist/tools/redialog.js.map +1 -0
  186. package/dist/tools/reflect.d.ts +4 -0
  187. package/dist/tools/reflect.d.ts.map +1 -0
  188. package/dist/tools/reflect.js +86 -0
  189. package/dist/tools/reflect.js.map +1 -0
  190. package/dist/tools/reject.d.ts +4 -0
  191. package/dist/tools/reject.d.ts.map +1 -0
  192. package/dist/tools/reject.js +57 -0
  193. package/dist/tools/reject.js.map +1 -0
  194. package/dist/tools/reskill.d.ts +4 -0
  195. package/dist/tools/reskill.d.ts.map +1 -0
  196. package/dist/tools/reskill.js +63 -0
  197. package/dist/tools/reskill.js.map +1 -0
  198. package/dist/tools/resume.d.ts +4 -0
  199. package/dist/tools/resume.d.ts.map +1 -0
  200. package/dist/tools/resume.js +56 -0
  201. package/dist/tools/resume.js.map +1 -0
  202. package/dist/tools/reverse.d.ts +4 -0
  203. package/dist/tools/reverse.d.ts.map +1 -0
  204. package/dist/tools/reverse.js +32 -0
  205. package/dist/tools/reverse.js.map +1 -0
  206. package/dist/tools/save-canon.d.ts +4 -0
  207. package/dist/tools/save-canon.d.ts.map +1 -0
  208. package/dist/tools/save-canon.js +97 -0
  209. package/dist/tools/save-canon.js.map +1 -0
  210. package/dist/tools/start.d.ts +4 -0
  211. package/dist/tools/start.d.ts.map +1 -0
  212. package/dist/tools/start.js +83 -0
  213. package/dist/tools/start.js.map +1 -0
  214. package/dist/tools/translate.d.ts +4 -0
  215. package/dist/tools/translate.d.ts.map +1 -0
  216. package/dist/tools/translate.js +102 -0
  217. package/dist/tools/translate.js.map +1 -0
  218. package/dist/tools/update.d.ts +4 -0
  219. package/dist/tools/update.d.ts.map +1 -0
  220. package/dist/tools/update.js +42 -0
  221. package/dist/tools/update.js.map +1 -0
  222. package/dist/tools/validate.d.ts +4 -0
  223. package/dist/tools/validate.d.ts.map +1 -0
  224. package/dist/tools/validate.js +86 -0
  225. package/dist/tools/validate.js.map +1 -0
  226. package/dist/utils/response.d.ts +12 -0
  227. package/dist/utils/response.d.ts.map +1 -0
  228. package/dist/utils/response.js +18 -0
  229. package/dist/utils/response.js.map +1 -0
  230. package/package.json +37 -0
  231. package/protocol/commands/amend.md +188 -0
  232. package/protocol/commands/build.md +90 -0
  233. package/protocol/commands/check.md +255 -0
  234. package/protocol/commands/create-dialog.md +81 -0
  235. package/protocol/commands/decompose.md +230 -0
  236. package/protocol/commands/dialog.md +173 -0
  237. package/protocol/commands/help.md +121 -0
  238. package/protocol/commands/migrate.md +173 -0
  239. package/protocol/commands/onboard.md +210 -0
  240. package/protocol/commands/quick.md +170 -0
  241. package/protocol/commands/redialog.md +73 -0
  242. package/protocol/commands/reflect.md +136 -0
  243. package/protocol/commands/resume.md +148 -0
  244. package/protocol/commands/reverse.md +312 -0
  245. package/protocol/commands/start.md +220 -0
  246. package/protocol/commands/translate.md +157 -0
  247. package/protocol/commands/update.md +205 -0
  248. package/protocol/core-advanced.md +188 -0
  249. package/protocol/core.md +274 -0
  250. package/protocol/pantion-future-prompt.md +88 -0
  251. package/protocol/pantion-intent.md +78 -0
  252. package/protocol/templates/acceptance-tests.md +116 -0
  253. package/protocol/templates/behavior-map.md +135 -0
  254. package/protocol/templates/traceability-map.md +56 -0
  255. package/souls/beginner/rules.md +34 -0
  256. package/souls/beginner/soul.json +6 -0
  257. package/souls/default/rules.md +25 -0
  258. package/souls/default/soul.json +6 -0
  259. package/souls/young/rules.md +67 -0
  260. package/souls/young/soul.json +6 -0
@@ -0,0 +1,320 @@
1
+ import { extractConvergenceStamp, extractOpenQuestionIds } from '../protocol/stamp-parser.js';
2
+ /**
3
+ * Evaluate the 12-category readiness checklist against dialog content and stamp.
4
+ */
5
+ function evaluateChecklist(dialog, stamp) {
6
+ const allContent = dialog.map((m) => m.content).join(' ');
7
+ const lc = allContent.toLowerCase();
8
+ const check = (name, test, detail) => {
9
+ const status = test();
10
+ return { name, status, detail: status !== 'pass' ? detail?.() : undefined };
11
+ };
12
+ return [
13
+ // 1. Canon status
14
+ check('Canon status', () => {
15
+ if (!stamp)
16
+ return 'fail';
17
+ if (stamp.type === 'draft')
18
+ return 'fail';
19
+ return stamp.date ? 'pass' : 'warning';
20
+ }, () => 'No valid convergence stamp or DRAFT status'),
21
+ // 2. Intent clarity
22
+ check('Intent clarity', () => {
23
+ const hasIntent = /\b(intent|purpose|goal|doel|wat .+ doet|wil .+ bouwen|want to build)\b/i.test(lc);
24
+ return hasIntent ? 'pass' : 'warning';
25
+ }, () => 'No clear intent/purpose detected in dialog'),
26
+ // 3. Observable success
27
+ check('Observable success', () => {
28
+ const hasSuccess = /\b(success|criteria|done|klaar|geslaagd|verificat|zichtbaar|observable|verifiable)\b/i.test(lc);
29
+ return hasSuccess ? 'pass' : 'warning';
30
+ }, () => 'No success criteria detected in dialog'),
31
+ // 4. Inputs complete
32
+ check('Inputs complete', () => {
33
+ const hasInputs = /\b(input|invoer|receives|ontvangt|trigger|click|klik|message|bericht)\b/i.test(lc);
34
+ return hasInputs ? 'pass' : 'warning';
35
+ }, () => 'No explicit inputs detected in dialog'),
36
+ // 5. Outputs unambiguous
37
+ check('Outputs unambiguous', () => {
38
+ const hasOutputs = /\b(output|uitvoer|shows|toont|displays|returns|sends|stuurt|produces|geeft)\b/i.test(lc);
39
+ return hasOutputs ? 'pass' : 'warning';
40
+ }, () => 'No explicit outputs detected in dialog'),
41
+ // 6. Failure specified
42
+ check('Failure specified', () => {
43
+ const hasFailure = /\b(fail|error|fout|mislukt|falen|probleem|oeps|fallback|graceful|retry)\b/i.test(lc);
44
+ return hasFailure ? 'pass' : 'warning';
45
+ }, () => 'No failure behavior detected in dialog'),
46
+ // 7. Constraints absolute
47
+ check('Constraints absolute', () => {
48
+ const hasConstraints = stamp.stabilityZones.length > 0 ||
49
+ /\b(constraint|must|never|always|nooit|altijd|verplicht|forbidden|verboden)\b/i.test(lc);
50
+ return hasConstraints ? 'pass' : 'warning';
51
+ }, () => 'No absolute constraints detected'),
52
+ // 8. Non-goals documented
53
+ check('Non-goals documented', () => {
54
+ const hasNonGoals = /\b(non-goal|not do|does not|niet doen|geen scope|out of scope|niet-doel|geen .+ functie)\b/i.test(lc);
55
+ return hasNonGoals ? 'pass' : 'warning';
56
+ }, () => 'No explicit non-goals detected in dialog'),
57
+ // 9. Ambiguity handled (with OQ-ID consistency when present)
58
+ check('Ambiguity handled', () => {
59
+ // Extract OQ-IDs from dialog content
60
+ const dialogOQs = extractOpenQuestionIds(allContent);
61
+ if (dialogOQs.length === 0) {
62
+ // No OQ-IDs in dialog — fall back to plain stamp check
63
+ if (stamp.openQuestions.length > 0)
64
+ return 'fail';
65
+ return 'pass';
66
+ }
67
+ // OQ-IDs are present — validate consistency
68
+ const dialogOQIds = new Set(dialogOQs.map(q => q.id));
69
+ const resolvedIds = new Set((stamp.resolvedQuestions ?? []).map(q => q.id));
70
+ // Check for duplicate IDs (already deduplicated by extractOpenQuestionIds,
71
+ // but check raw text for actual duplicates)
72
+ const rawPattern = /OPEN QUESTION \[OQ-(\d+)\]/gi;
73
+ const rawIds = [];
74
+ let rawMatch;
75
+ while ((rawMatch = rawPattern.exec(allContent)) !== null) {
76
+ rawIds.push(`OQ-${rawMatch[1]}`);
77
+ }
78
+ const duplicates = rawIds.filter((id, idx) => rawIds.indexOf(id) !== idx);
79
+ if (duplicates.length > 0)
80
+ return 'warning';
81
+ // Check: all dialog OQ-IDs should be either open in stamp or resolved
82
+ const stampOpenTexts = stamp.openQuestions.map(q => q.toLowerCase());
83
+ for (const oqId of dialogOQIds) {
84
+ const isResolved = resolvedIds.has(oqId);
85
+ const isInStampOpen = stampOpenTexts.some(t => t.includes(oqId.toLowerCase()));
86
+ if (!isResolved && !isInStampOpen) {
87
+ // OQ-ID found in dialog but not accounted for in stamp
88
+ if (stamp.type !== 'draft')
89
+ return 'warning';
90
+ }
91
+ }
92
+ // If converged and there are unresolved OQ-IDs (in stamp.openQuestions)
93
+ if (stamp.type !== 'draft' && stamp.openQuestions.length > 0)
94
+ return 'fail';
95
+ return 'pass';
96
+ }, () => {
97
+ const dialogOQs = extractOpenQuestionIds(allContent);
98
+ if (dialogOQs.length === 0) {
99
+ return `Open questions remain: ${stamp.openQuestions.join(', ')}`;
100
+ }
101
+ // Check for duplicates
102
+ const rawPattern = /OPEN QUESTION \[OQ-(\d+)\]/gi;
103
+ const rawIds = [];
104
+ let rawMatch;
105
+ while ((rawMatch = rawPattern.exec(allContent)) !== null) {
106
+ rawIds.push(`OQ-${rawMatch[1]}`);
107
+ }
108
+ const duplicates = [...new Set(rawIds.filter((id, idx) => rawIds.indexOf(id) !== idx))];
109
+ if (duplicates.length > 0) {
110
+ return `Duplicate OQ-IDs: ${duplicates.join(', ')}`;
111
+ }
112
+ const resolvedCount = (stamp.resolvedQuestions ?? []).length;
113
+ if (stamp.openQuestions.length > 0) {
114
+ return `Open questions remain: ${stamp.openQuestions.join(', ')}`;
115
+ }
116
+ return `${dialogOQs.length} questions tracked, ${resolvedCount} resolved`;
117
+ }),
118
+ // 10. Authority Budget
119
+ check('Authority Budget', () => {
120
+ const raw = stamp.raw.toLowerCase();
121
+ const hasRights = /authority budget rights:\s*(complete|partial)/i.test(raw);
122
+ const hasConsumption = /authority budget consumption:\s*(complete|partial|n\/a)/i.test(raw);
123
+ if (hasRights && hasConsumption)
124
+ return 'pass';
125
+ if (hasRights || hasConsumption)
126
+ return 'warning';
127
+ // Also check dialog content for authority-related terms
128
+ const inContent = /\b(authority|budget|allowed|forbidden|data.?access|data.?retention|audit)\b/i.test(lc);
129
+ return inContent ? 'warning' : 'fail';
130
+ }, () => 'Authority Budget not fully specified in stamp'),
131
+ // 11. Inference Policy
132
+ check('Inference Policy', () => {
133
+ return stamp.inferencePolicy ? 'pass' : 'warning';
134
+ }, () => 'Inference policy not specified'),
135
+ // 12. Dialog stability
136
+ check('Dialog stability', () => {
137
+ // If converged and no open questions, we consider it stable
138
+ if (stamp.type !== 'draft' && stamp.openQuestions.length === 0)
139
+ return 'pass';
140
+ return 'warning';
141
+ }, () => 'Dialog may not be fully stable'),
142
+ // 13. Lineage trace
143
+ check('Lineage trace', () => {
144
+ const rawStatus = stamp.raw.match(/STATUS:\s*(.+)/i)?.[1]?.trim().toUpperCase() ?? '';
145
+ // Content without stamp block to avoid self-matching
146
+ const contentWithoutStamp = allContent.replace(stamp.raw, '');
147
+ if (rawStatus.includes('AMENDED')) {
148
+ // Amended canon must have an Amendment section in the dialog
149
+ const hasAmendment = /# ?Amendment/i.test(contentWithoutStamp);
150
+ return hasAmendment ? 'pass' : 'fail';
151
+ }
152
+ if (rawStatus.includes('RECONVERGED')) {
153
+ // Reconverged canon should have reconvergence context
154
+ const hasReconvergence = /reconverg|gap.?analysis|supplementary/i.test(contentWithoutStamp);
155
+ return hasReconvergence ? 'pass' : 'warning';
156
+ }
157
+ // Not amended or reconverged — lineage is n/a
158
+ return 'pass';
159
+ }, () => {
160
+ const rawStatus = stamp.raw.match(/STATUS:\s*(.+)/i)?.[1]?.trim().toUpperCase() ?? '';
161
+ if (rawStatus.includes('AMENDED'))
162
+ return 'Stamp is AMENDED but no Amendment section found in dialog';
163
+ if (rawStatus.includes('RECONVERGED'))
164
+ return 'Stamp is RECONVERGED but no reconvergence context found in dialog';
165
+ return 'Lineage trace incomplete';
166
+ }),
167
+ ];
168
+ }
169
+ /**
170
+ * Compute the total outcome from categories and issues.
171
+ * PASS: all categories pass (or na), no error issues
172
+ * WARN: no fail categories, but warnings exist
173
+ * FAIL: at least 1 fail category or error issue
174
+ */
175
+ function computeTotalOutcome(categories, issues) {
176
+ const hasFail = categories.some((c) => c.status === 'fail');
177
+ const hasError = issues.some((i) => i.severity === 'error');
178
+ if (hasFail || hasError)
179
+ return 'FAIL';
180
+ const hasWarning = categories.some((c) => c.status === 'warning');
181
+ if (hasWarning)
182
+ return 'WARN';
183
+ return 'PASS';
184
+ }
185
+ /**
186
+ * Structural convergence validation (Level 2).
187
+ * Checks the dialog for required convergence elements with 12-category scoring.
188
+ */
189
+ export function validateConvergence(dialog) {
190
+ const issues = [];
191
+ let stamp;
192
+ if (dialog.length === 0) {
193
+ return {
194
+ valid: false,
195
+ status: 'open',
196
+ issues: [{ severity: 'error', message: 'Dialog is empty' }],
197
+ openQuestions: [],
198
+ };
199
+ }
200
+ // Find the last assistant message with a stamp
201
+ const assistantMessages = dialog.filter((m) => m.role === 'assistant');
202
+ const lastAssistant = assistantMessages[assistantMessages.length - 1];
203
+ if (!lastAssistant) {
204
+ issues.push({ severity: 'error', message: 'No assistant messages found' });
205
+ return { valid: false, status: 'open', issues, openQuestions: [] };
206
+ }
207
+ // Check for convergence stamp in the last assistant message
208
+ stamp = extractConvergenceStamp(lastAssistant.content) ?? undefined;
209
+ if (!stamp) {
210
+ // Also check all assistant messages (stamp might not be in the very last one)
211
+ for (const msg of [...assistantMessages].reverse()) {
212
+ const found = extractConvergenceStamp(msg.content);
213
+ if (found) {
214
+ stamp = found ?? undefined;
215
+ break;
216
+ }
217
+ }
218
+ }
219
+ if (!stamp) {
220
+ issues.push({ severity: 'error', message: 'No DIALOGSPEC STAMP found in dialog' });
221
+ return { valid: false, status: 'open', issues, openQuestions: [] };
222
+ }
223
+ if (stamp.type === 'draft') {
224
+ issues.push({ severity: 'info', message: 'Stamp indicates DRAFT status' });
225
+ return {
226
+ valid: false,
227
+ status: 'open',
228
+ issues,
229
+ openQuestions: stamp.openQuestions,
230
+ stamp,
231
+ };
232
+ }
233
+ // Check required stamp fields
234
+ if (!stamp.date) {
235
+ issues.push({ severity: 'error', message: 'Stamp missing DATE field' });
236
+ }
237
+ if (!stamp.canonType) {
238
+ issues.push({ severity: 'warning', message: 'Stamp missing CANON TYPE field' });
239
+ }
240
+ if (!stamp.inferencePolicy) {
241
+ issues.push({ severity: 'warning', message: 'Stamp missing INFERENCE POLICY field' });
242
+ }
243
+ // Open questions must be none
244
+ if (stamp.openQuestions.length > 0) {
245
+ issues.push({
246
+ severity: 'error',
247
+ message: `OPEN QUESTIONS is not empty: ${stamp.openQuestions.join(', ')}`,
248
+ });
249
+ }
250
+ // Check for stability zones (HARD constraints)
251
+ if (stamp.stabilityZones.length === 0) {
252
+ issues.push({ severity: 'warning', message: 'No stability zones (HARD constraints) listed in stamp' });
253
+ }
254
+ // Check for Convergence Verification Table (recommended before stamp)
255
+ const allAssistantContent = assistantMessages.map((m) => m.content).join('\n');
256
+ if (!/convergence verification/i.test(allAssistantContent)) {
257
+ issues.push({ severity: 'info', message: 'No Convergence Verification Table found. Consider adding one before the stamp to confirm all criteria are met.' });
258
+ }
259
+ // Run the 12-category readiness checklist
260
+ const categories = evaluateChecklist(dialog, stamp);
261
+ // Add issues from category evaluation
262
+ for (const cat of categories) {
263
+ if (cat.status === 'fail') {
264
+ issues.push({ severity: 'error', message: `Checklist FAIL: ${cat.name} — ${cat.detail ?? 'not satisfied'}` });
265
+ }
266
+ else if (cat.status === 'warning' && cat.detail) {
267
+ issues.push({ severity: 'warning', message: `Checklist WARNING: ${cat.name} — ${cat.detail}` });
268
+ }
269
+ }
270
+ const score = categories.filter((c) => c.status === 'pass').length;
271
+ const hasErrors = issues.some((i) => i.severity === 'error');
272
+ const totalOutcome = computeTotalOutcome(categories, issues);
273
+ return {
274
+ valid: !hasErrors,
275
+ status: hasErrors ? 'open' : 'converged',
276
+ issues,
277
+ openQuestions: stamp.openQuestions,
278
+ stamp,
279
+ categories,
280
+ score,
281
+ totalOutcome,
282
+ };
283
+ }
284
+ /**
285
+ * Validate an existing canon file on disk (used by pantion_check).
286
+ * Parses the dialog from the file content and validates.
287
+ */
288
+ export function validateCanonFile(dialogContent) {
289
+ const messages = parseDialogFile(dialogContent);
290
+ return validateConvergence(messages);
291
+ }
292
+ /**
293
+ * Parse a dialog .md file back into messages.
294
+ */
295
+ function parseDialogFile(content) {
296
+ const messages = [];
297
+ const lines = content.split('\n');
298
+ let current = null;
299
+ for (const line of lines) {
300
+ const humanMatch = line.match(/^HUMAN:\s*(.*)/);
301
+ const assistantMatch = line.match(/^ASSISTANT:\s*(.*)/);
302
+ if (humanMatch) {
303
+ if (current)
304
+ messages.push(current);
305
+ current = { role: 'user', content: humanMatch[1] };
306
+ }
307
+ else if (assistantMatch) {
308
+ if (current)
309
+ messages.push(current);
310
+ current = { role: 'assistant', content: assistantMatch[1] };
311
+ }
312
+ else if (current) {
313
+ current.content += '\n' + line;
314
+ }
315
+ }
316
+ if (current)
317
+ messages.push(current);
318
+ return messages;
319
+ }
320
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/core/canon/validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Session, CanonMetadata } from '../types.js';
2
+ /**
3
+ * Get the dialog canon directory: dialogs/{dialogName}/canon/
4
+ */
5
+ export declare function dialogCanonDir(projectPath: string, dialogName: string): string;
6
+ /**
7
+ * Write a dialog dialog file (THE CANON for the dialog).
8
+ */
9
+ export declare function writeDialogCanonFile(session: Session, dialogName: string, date: string, projectPath: string, mode?: 'dialog' | 'full', metadata?: CanonMetadata): string;
10
+ /**
11
+ * Write a dialog summary file (DERIVED from dialog canon).
12
+ */
13
+ export declare function writeDialogSummaryFile(dialogName: string, date: string, summaryContent: string, projectPath: string): string;
14
+ /**
15
+ * Check if a dialog has a canon (is a dynamic dialog).
16
+ */
17
+ export declare function dialogHasCanon(projectPath: string, dialogName: string): boolean;
18
+ /**
19
+ * Read a dialog's canon dialog.
20
+ */
21
+ export declare function readDialogCanon(projectPath: string, dialogName: string): string | null;
22
+ //# sourceMappingURL=canon-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canon-writer.d.ts","sourceRoot":"","sources":["../../../src/core/dialog/canon-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI1D;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,EACxB,QAAQ,CAAC,EAAE,aAAa,GACvB,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,GAClB,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAI/E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAItF"}
@@ -0,0 +1,96 @@
1
+ import { resolve } from 'node:path';
2
+ import { existsSync } from 'node:fs';
3
+ import { writeFile, readFileSafe, ensureDir, assertSafeName } from '../utils/fs.js';
4
+ import { createPendingHumanStamp, createAutoApprovedHumanStamp, formatCanonMetadata } from '../protocol/stamp-parser.js';
5
+ /**
6
+ * Get the dialog canon directory: dialogs/{dialogName}/canon/
7
+ */
8
+ export function dialogCanonDir(projectPath, dialogName) {
9
+ return resolve(projectPath, 'skills', dialogName, 'canon');
10
+ }
11
+ /**
12
+ * Write a dialog dialog file (THE CANON for the dialog).
13
+ */
14
+ export function writeDialogCanonFile(session, dialogName, date, projectPath, mode, metadata) {
15
+ assertSafeName(dialogName);
16
+ const dir = dialogCanonDir(projectPath, dialogName);
17
+ ensureDir(dir);
18
+ const content = formatDialogCanon(session, dialogName, mode, metadata);
19
+ const dialogPath = resolve(dir, 'dialog.md');
20
+ writeFile(dialogPath, content);
21
+ return dialogPath;
22
+ }
23
+ /**
24
+ * Write a dialog summary file (DERIVED from dialog canon).
25
+ */
26
+ export function writeDialogSummaryFile(dialogName, date, summaryContent, projectPath) {
27
+ assertSafeName(dialogName);
28
+ const dir = dialogCanonDir(projectPath, dialogName);
29
+ ensureDir(dir);
30
+ // Normalize literal \n sequences to real newlines (client may send escaped strings)
31
+ let content = normalizeLiteralNewlines(summaryContent);
32
+ if (!content.includes('Derived from:')) {
33
+ content = `<!-- Derived from: dialogs/${dialogName}/canon/dialog.md, ${date} -->\n<!-- This is a DERIVED file — the dialog dialog is the only source of truth -->\n\n${content}`;
34
+ }
35
+ const summaryPath = resolve(dir, 'summary.md');
36
+ writeFile(summaryPath, content);
37
+ return summaryPath;
38
+ }
39
+ /**
40
+ * Check if a dialog has a canon (is a dynamic dialog).
41
+ */
42
+ export function dialogHasCanon(projectPath, dialogName) {
43
+ assertSafeName(dialogName);
44
+ const dialogPath = resolve(dialogCanonDir(projectPath, dialogName), 'dialog.md');
45
+ return existsSync(dialogPath);
46
+ }
47
+ /**
48
+ * Read a dialog's canon dialog.
49
+ */
50
+ export function readDialogCanon(projectPath, dialogName) {
51
+ assertSafeName(dialogName);
52
+ const dialogPath = resolve(dialogCanonDir(projectPath, dialogName), 'dialog.md');
53
+ return readFileSafe(dialogPath);
54
+ }
55
+ /**
56
+ * Normalize literal \n (backslash + n) sequences to real newlines.
57
+ * Client LLMs sometimes send escaped strings via MCP.
58
+ */
59
+ function normalizeLiteralNewlines(text) {
60
+ if (!text.includes('\n') && text.includes('\\n')) {
61
+ return text.replace(/\\n/g, '\n');
62
+ }
63
+ return text;
64
+ }
65
+ function formatDialogCanon(session, dialogName, mode, metadata) {
66
+ const lines = [];
67
+ lines.push('# Dialog DialogSpec Dialog');
68
+ lines.push(`<!-- Dialog canon for: ${dialogName} -->`);
69
+ lines.push('<!-- This is the canon — the verbatim dialog is the only source of truth -->');
70
+ lines.push('<!-- All dialog files (dialog.json, convergence-rules.md, translate.md, prompts/) are derived from this dialog -->');
71
+ lines.push('');
72
+ // Only add stampRaw at the top if the stamp is NOT already in the dialog messages.
73
+ const stampInMessages = session.stampRaw && session.messages.some((msg) => msg.content.includes('=== DIALOGSPEC STAMP ==='));
74
+ if (session.stampRaw && !stampInMessages) {
75
+ lines.push(session.stampRaw);
76
+ lines.push('');
77
+ }
78
+ lines.push('---');
79
+ lines.push('');
80
+ for (const msg of session.messages) {
81
+ const role = msg.role === 'user' ? 'HUMAN' : 'ASSISTANT';
82
+ lines.push(`${role}: ${msg.content}`);
83
+ lines.push('');
84
+ }
85
+ // Append CANON METADATA block (server-generated replay context)
86
+ if (metadata) {
87
+ lines.push('');
88
+ lines.push(formatCanonMetadata(metadata));
89
+ }
90
+ // Append HUMAN STAMP block (auto-approved for dialog mode, pending for full mode)
91
+ lines.push('');
92
+ lines.push(mode === 'dialog' ? createAutoApprovedHumanStamp() : createPendingHumanStamp());
93
+ lines.push('');
94
+ return lines.join('\n');
95
+ }
96
+ //# sourceMappingURL=canon-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canon-writer.js","sourceRoot":"","sources":["../../../src/core/dialog/canon-writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Dialog } from '../types.js';
2
+ /**
3
+ * List all available dialogs (deduplicated by name, project > user > bundled).
4
+ */
5
+ export declare function listDialogs(projectPath: string, dialogsDir?: string): Dialog[];
6
+ /**
7
+ * Get a specific dialog by name.
8
+ */
9
+ export declare function getDialog(name: string, projectPath: string, dialogsDir?: string): Dialog | null;
10
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/dialog/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAkB,MAAM,aAAa,CAAC;AA0F1D;;GAEG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB9E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE/F"}
@@ -0,0 +1,102 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ /**
5
+ * Dialog search order: project-local > user-global > bundled.
6
+ * dialogsDir allows explicitly specifying where bundled dialogs live.
7
+ */
8
+ function getDialogDirs(projectPath, dialogsDir) {
9
+ const dirs = [];
10
+ // Project-local dialogs
11
+ const projectDialogs = resolve(projectPath, 'dialogs');
12
+ if (existsSync(projectDialogs)) {
13
+ dirs.push({ dir: projectDialogs, source: 'project' });
14
+ }
15
+ // User-global dialogs
16
+ const userDialogs = resolve(homedir(), '.pantion', 'dialogs');
17
+ if (existsSync(userDialogs)) {
18
+ dirs.push({ dir: userDialogs, source: 'user' });
19
+ }
20
+ // Bundled dialogs (explicit or relative)
21
+ if (dialogsDir && existsSync(dialogsDir)) {
22
+ dirs.push({ dir: dialogsDir, source: 'bundled' });
23
+ }
24
+ return dirs;
25
+ }
26
+ function loadDialog(dir, source) {
27
+ const manifestPath = resolve(dir, 'dialog.json');
28
+ if (!existsSync(manifestPath))
29
+ return null;
30
+ try {
31
+ const raw = JSON.parse(readFileSync(manifestPath, 'utf-8'));
32
+ if (!raw ||
33
+ typeof raw !== 'object' ||
34
+ typeof raw.name !== 'string' ||
35
+ typeof raw.displayName !== 'string' ||
36
+ typeof raw.description !== 'string' ||
37
+ typeof raw.version !== 'string' ||
38
+ !Array.isArray(raw.keywords)) {
39
+ return null;
40
+ }
41
+ const manifest = raw;
42
+ const convergenceRulesPath = resolve(dir, 'convergence-rules.md');
43
+ const translatePath = resolve(dir, 'translate.md');
44
+ const convergenceRules = existsSync(convergenceRulesPath)
45
+ ? readFileSync(convergenceRulesPath, 'utf-8')
46
+ : '';
47
+ const translatePrompt = existsSync(translatePath)
48
+ ? readFileSync(translatePath, 'utf-8')
49
+ : '';
50
+ const prompts = {};
51
+ const promptsDir = resolve(dir, 'prompts');
52
+ if (existsSync(promptsDir)) {
53
+ for (const file of readdirSync(promptsDir)) {
54
+ if (file.endsWith('.md')) {
55
+ prompts[file.replace('.md', '')] = readFileSync(resolve(promptsDir, file), 'utf-8');
56
+ }
57
+ }
58
+ }
59
+ // Check for dynamic dialog canon
60
+ const canonDialogPath = resolve(dir, 'canon', 'dialog.md');
61
+ const hasCanon = existsSync(canonDialogPath);
62
+ return {
63
+ manifest,
64
+ convergenceRules,
65
+ translatePrompt,
66
+ prompts,
67
+ path: dir,
68
+ source: hasCanon ? 'dynamic' : source,
69
+ hasCanon,
70
+ };
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ /**
77
+ * List all available dialogs (deduplicated by name, project > user > bundled).
78
+ */
79
+ export function listDialogs(projectPath, dialogsDir) {
80
+ const dialogs = new Map();
81
+ // Iterate in reverse priority order so higher-priority overwrites
82
+ const dirs = getDialogDirs(projectPath, dialogsDir).reverse();
83
+ for (const { dir, source } of dirs) {
84
+ if (!existsSync(dir))
85
+ continue;
86
+ for (const entry of readdirSync(dir)) {
87
+ const entryDir = resolve(dir, entry);
88
+ const dlg = loadDialog(entryDir, source);
89
+ if (dlg) {
90
+ dialogs.set(dlg.manifest.name, dlg);
91
+ }
92
+ }
93
+ }
94
+ return Array.from(dialogs.values());
95
+ }
96
+ /**
97
+ * Get a specific dialog by name.
98
+ */
99
+ export function getDialog(name, projectPath, dialogsDir) {
100
+ return listDialogs(projectPath, dialogsDir).find((s) => s.manifest.name === name) ?? null;
101
+ }
102
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/dialog/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { Dialog } from '../types.js';
2
+ export interface DialogSelection {
3
+ dialog: Dialog;
4
+ matchedKeywords: string[];
5
+ }
6
+ /**
7
+ * Auto-select a dialog based on the user's first message.
8
+ * Matches against dialog keywords. Returns the dialog and which keywords matched.
9
+ */
10
+ export declare function autoSelectDialog(userMessage: string, projectPath: string, dialogsDir?: string): DialogSelection | null;
11
+ //# sourceMappingURL=selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selector.d.ts","sourceRoot":"","sources":["../../../src/core/dialog/selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CA4BtH"}
@@ -0,0 +1,32 @@
1
+ import { listDialogs } from './registry.js';
2
+ /**
3
+ * Auto-select a dialog based on the user's first message.
4
+ * Matches against dialog keywords. Returns the dialog and which keywords matched.
5
+ */
6
+ export function autoSelectDialog(userMessage, projectPath, dialogsDir) {
7
+ const allDialogs = listDialogs(projectPath, dialogsDir);
8
+ if (allDialogs.length === 0)
9
+ return null;
10
+ const lower = userMessage.toLowerCase();
11
+ let bestMatch = null;
12
+ let bestScore = 0;
13
+ let bestKeywords = [];
14
+ for (const dlg of allDialogs) {
15
+ const matched = [];
16
+ for (const keyword of dlg.manifest.keywords) {
17
+ if (lower.includes(keyword.toLowerCase())) {
18
+ matched.push(keyword);
19
+ }
20
+ }
21
+ if (matched.length > bestScore ||
22
+ (matched.length === bestScore && bestMatch && dlg.manifest.name < bestMatch.manifest.name)) {
23
+ bestScore = matched.length;
24
+ bestMatch = dlg;
25
+ bestKeywords = matched;
26
+ }
27
+ }
28
+ if (!bestMatch)
29
+ return null;
30
+ return { dialog: bestMatch, matchedKeywords: bestKeywords };
31
+ }
32
+ //# sourceMappingURL=selector.js.map