@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.
- package/dialogs/dialog-builder/convergence-rules.md +64 -0
- package/dialogs/dialog-builder/dialog.json +10 -0
- package/dialogs/dialog-builder/prompts/convergence-intro.md +21 -0
- package/dialogs/dialog-builder/prompts/translate-intro.md +17 -0
- package/dialogs/dialog-builder/translate.md +46 -0
- package/dialogs/image/convergence-rules.md +55 -0
- package/dialogs/image/dialog.json +12 -0
- package/dialogs/image/prompts/convergence-intro.md +25 -0
- package/dialogs/image/prompts/translate-intro.md +37 -0
- package/dialogs/image/translate.md +67 -0
- package/dialogs/software/convergence-rules.md +29 -0
- package/dialogs/software/dialog.json +12 -0
- package/dialogs/software/prompts/convergence-intro.md +22 -0
- package/dialogs/software/prompts/translate-intro.md +19 -0
- package/dialogs/software/translate.md +74 -0
- package/dialogs/software-brownfield/convergence-rules.md +109 -0
- package/dialogs/software-brownfield/dialog.json +12 -0
- package/dialogs/software-brownfield/prompts/convergence-intro.md +26 -0
- package/dialogs/software-brownfield/prompts/translate-intro.md +13 -0
- package/dialogs/software-brownfield/translate.md +56 -0
- package/dialogs/video/convergence-rules.md +96 -0
- package/dialogs/video/dialog.json +12 -0
- package/dialogs/video/prompts/convergence-intro.md +28 -0
- package/dialogs/video/prompts/translate-intro.md +41 -0
- package/dialogs/video/translate.md +81 -0
- package/dist/core/canon/index-manager.d.ts +27 -0
- package/dist/core/canon/index-manager.d.ts.map +1 -0
- package/dist/core/canon/index-manager.js +127 -0
- package/dist/core/canon/index-manager.js.map +1 -0
- package/dist/core/canon/manifest.d.ts +21 -0
- package/dist/core/canon/manifest.d.ts.map +1 -0
- package/dist/core/canon/manifest.js +56 -0
- package/dist/core/canon/manifest.js.map +1 -0
- package/dist/core/canon/validator.d.ts +12 -0
- package/dist/core/canon/validator.d.ts.map +1 -0
- package/dist/core/canon/validator.js +320 -0
- package/dist/core/canon/validator.js.map +1 -0
- package/dist/core/dialog/canon-writer.d.ts +22 -0
- package/dist/core/dialog/canon-writer.d.ts.map +1 -0
- package/dist/core/dialog/canon-writer.js +96 -0
- package/dist/core/dialog/canon-writer.js.map +1 -0
- package/dist/core/dialog/registry.d.ts +10 -0
- package/dist/core/dialog/registry.d.ts.map +1 -0
- package/dist/core/dialog/registry.js +102 -0
- package/dist/core/dialog/registry.js.map +1 -0
- package/dist/core/dialog/selector.d.ts +11 -0
- package/dist/core/dialog/selector.d.ts.map +1 -0
- package/dist/core/dialog/selector.js +32 -0
- package/dist/core/dialog/selector.js.map +1 -0
- package/dist/core/index.d.ts +20 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +30 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/protocol/convergence.d.ts +11 -0
- package/dist/core/protocol/convergence.d.ts.map +1 -0
- package/dist/core/protocol/convergence.js +30 -0
- package/dist/core/protocol/convergence.js.map +1 -0
- package/dist/core/protocol/loader.d.ts +6 -0
- package/dist/core/protocol/loader.d.ts.map +1 -0
- package/dist/core/protocol/loader.js +31 -0
- package/dist/core/protocol/loader.js.map +1 -0
- package/dist/core/protocol/stamp-parser.d.ts +46 -0
- package/dist/core/protocol/stamp-parser.d.ts.map +1 -0
- package/dist/core/protocol/stamp-parser.js +333 -0
- package/dist/core/protocol/stamp-parser.js.map +1 -0
- package/dist/core/protocol/system-prompt.d.ts +16 -0
- package/dist/core/protocol/system-prompt.d.ts.map +1 -0
- package/dist/core/protocol/system-prompt.js +68 -0
- package/dist/core/protocol/system-prompt.js.map +1 -0
- package/dist/core/session/canon-writer.d.ts +33 -0
- package/dist/core/session/canon-writer.d.ts.map +1 -0
- package/dist/core/session/canon-writer.js +152 -0
- package/dist/core/session/canon-writer.js.map +1 -0
- package/dist/core/session/manager.d.ts +10 -0
- package/dist/core/session/manager.d.ts.map +1 -0
- package/dist/core/session/manager.js +105 -0
- package/dist/core/session/manager.js.map +1 -0
- package/dist/core/skill/canon-writer.d.ts +22 -0
- package/dist/core/skill/canon-writer.d.ts.map +1 -0
- package/dist/core/skill/canon-writer.js +96 -0
- package/dist/core/skill/canon-writer.js.map +1 -0
- package/dist/core/skill/registry.d.ts +10 -0
- package/dist/core/skill/registry.d.ts.map +1 -0
- package/dist/core/skill/registry.js +102 -0
- package/dist/core/skill/registry.js.map +1 -0
- package/dist/core/skill/selector.d.ts +11 -0
- package/dist/core/skill/selector.d.ts.map +1 -0
- package/dist/core/skill/selector.js +32 -0
- package/dist/core/skill/selector.js.map +1 -0
- package/dist/core/soul/registry.d.ts +10 -0
- package/dist/core/soul/registry.d.ts.map +1 -0
- package/dist/core/soul/registry.js +73 -0
- package/dist/core/soul/registry.js.map +1 -0
- package/dist/core/types.d.ts +154 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +6 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/utils/fs.d.ts +14 -0
- package/dist/core/utils/fs.d.ts.map +1 -0
- package/dist/core/utils/fs.js +44 -0
- package/dist/core/utils/fs.js.map +1 -0
- package/dist/core/utils/project-detect.d.ts +3 -0
- package/dist/core/utils/project-detect.d.ts.map +1 -0
- package/dist/core/utils/project-detect.js +38 -0
- package/dist/core/utils/project-detect.js.map +1 -0
- package/dist/feature-set.d.ts +14 -0
- package/dist/feature-set.d.ts.map +1 -0
- package/dist/feature-set.js +38 -0
- package/dist/feature-set.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +56 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/convergence-prompts.d.ts +4 -0
- package/dist/prompts/convergence-prompts.d.ts.map +1 -0
- package/dist/prompts/convergence-prompts.js +76 -0
- package/dist/prompts/convergence-prompts.js.map +1 -0
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +7 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/workflow-prompts.d.ts +9 -0
- package/dist/prompts/workflow-prompts.d.ts.map +1 -0
- package/dist/prompts/workflow-prompts.js +265 -0
- package/dist/prompts/workflow-prompts.js.map +1 -0
- package/dist/resources/canon-resources.d.ts +4 -0
- package/dist/resources/canon-resources.d.ts.map +1 -0
- package/dist/resources/canon-resources.js +164 -0
- package/dist/resources/canon-resources.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +47 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/amend.d.ts +4 -0
- package/dist/tools/amend.d.ts.map +1 -0
- package/dist/tools/amend.js +106 -0
- package/dist/tools/amend.js.map +1 -0
- package/dist/tools/approve.d.ts +4 -0
- package/dist/tools/approve.d.ts.map +1 -0
- package/dist/tools/approve.js +60 -0
- package/dist/tools/approve.js.map +1 -0
- package/dist/tools/check-convergence.d.ts +4 -0
- package/dist/tools/check-convergence.d.ts.map +1 -0
- package/dist/tools/check-convergence.js +50 -0
- package/dist/tools/check-convergence.js.map +1 -0
- package/dist/tools/check.d.ts +4 -0
- package/dist/tools/check.d.ts.map +1 -0
- package/dist/tools/check.js +190 -0
- package/dist/tools/check.js.map +1 -0
- package/dist/tools/create-dialog.d.ts +4 -0
- package/dist/tools/create-dialog.d.ts.map +1 -0
- package/dist/tools/create-dialog.js +58 -0
- package/dist/tools/create-dialog.js.map +1 -0
- package/dist/tools/create-skill.d.ts +4 -0
- package/dist/tools/create-skill.d.ts.map +1 -0
- package/dist/tools/create-skill.js +58 -0
- package/dist/tools/create-skill.js.map +1 -0
- package/dist/tools/decompose.d.ts +4 -0
- package/dist/tools/decompose.d.ts.map +1 -0
- package/dist/tools/decompose.js +56 -0
- package/dist/tools/decompose.js.map +1 -0
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +49 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list-canons.d.ts +4 -0
- package/dist/tools/list-canons.d.ts.map +1 -0
- package/dist/tools/list-canons.js +28 -0
- package/dist/tools/list-canons.js.map +1 -0
- package/dist/tools/migrate.d.ts +4 -0
- package/dist/tools/migrate.d.ts.map +1 -0
- package/dist/tools/migrate.js +38 -0
- package/dist/tools/migrate.js.map +1 -0
- package/dist/tools/onboard.d.ts +4 -0
- package/dist/tools/onboard.d.ts.map +1 -0
- package/dist/tools/onboard.js +27 -0
- package/dist/tools/onboard.js.map +1 -0
- package/dist/tools/reconverge.d.ts +4 -0
- package/dist/tools/reconverge.d.ts.map +1 -0
- package/dist/tools/reconverge.js +68 -0
- package/dist/tools/reconverge.js.map +1 -0
- package/dist/tools/redialog.d.ts +4 -0
- package/dist/tools/redialog.d.ts.map +1 -0
- package/dist/tools/redialog.js +63 -0
- package/dist/tools/redialog.js.map +1 -0
- package/dist/tools/reflect.d.ts +4 -0
- package/dist/tools/reflect.d.ts.map +1 -0
- package/dist/tools/reflect.js +86 -0
- package/dist/tools/reflect.js.map +1 -0
- package/dist/tools/reject.d.ts +4 -0
- package/dist/tools/reject.d.ts.map +1 -0
- package/dist/tools/reject.js +57 -0
- package/dist/tools/reject.js.map +1 -0
- package/dist/tools/reskill.d.ts +4 -0
- package/dist/tools/reskill.d.ts.map +1 -0
- package/dist/tools/reskill.js +63 -0
- package/dist/tools/reskill.js.map +1 -0
- package/dist/tools/resume.d.ts +4 -0
- package/dist/tools/resume.d.ts.map +1 -0
- package/dist/tools/resume.js +56 -0
- package/dist/tools/resume.js.map +1 -0
- package/dist/tools/reverse.d.ts +4 -0
- package/dist/tools/reverse.d.ts.map +1 -0
- package/dist/tools/reverse.js +32 -0
- package/dist/tools/reverse.js.map +1 -0
- package/dist/tools/save-canon.d.ts +4 -0
- package/dist/tools/save-canon.d.ts.map +1 -0
- package/dist/tools/save-canon.js +97 -0
- package/dist/tools/save-canon.js.map +1 -0
- package/dist/tools/start.d.ts +4 -0
- package/dist/tools/start.d.ts.map +1 -0
- package/dist/tools/start.js +83 -0
- package/dist/tools/start.js.map +1 -0
- package/dist/tools/translate.d.ts +4 -0
- package/dist/tools/translate.d.ts.map +1 -0
- package/dist/tools/translate.js +102 -0
- package/dist/tools/translate.js.map +1 -0
- package/dist/tools/update.d.ts +4 -0
- package/dist/tools/update.d.ts.map +1 -0
- package/dist/tools/update.js +42 -0
- package/dist/tools/update.js.map +1 -0
- package/dist/tools/validate.d.ts +4 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +86 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/utils/response.d.ts +12 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +18 -0
- package/dist/utils/response.js.map +1 -0
- package/package.json +37 -0
- package/protocol/commands/amend.md +188 -0
- package/protocol/commands/build.md +90 -0
- package/protocol/commands/check.md +255 -0
- package/protocol/commands/create-dialog.md +81 -0
- package/protocol/commands/decompose.md +230 -0
- package/protocol/commands/dialog.md +173 -0
- package/protocol/commands/help.md +121 -0
- package/protocol/commands/migrate.md +173 -0
- package/protocol/commands/onboard.md +210 -0
- package/protocol/commands/quick.md +170 -0
- package/protocol/commands/redialog.md +73 -0
- package/protocol/commands/reflect.md +136 -0
- package/protocol/commands/resume.md +148 -0
- package/protocol/commands/reverse.md +312 -0
- package/protocol/commands/start.md +220 -0
- package/protocol/commands/translate.md +157 -0
- package/protocol/commands/update.md +205 -0
- package/protocol/core-advanced.md +188 -0
- package/protocol/core.md +274 -0
- package/protocol/pantion-future-prompt.md +88 -0
- package/protocol/pantion-intent.md +78 -0
- package/protocol/templates/acceptance-tests.md +116 -0
- package/protocol/templates/behavior-map.md +135 -0
- package/protocol/templates/traceability-map.md +56 -0
- package/souls/beginner/rules.md +34 -0
- package/souls/beginner/soul.json +6 -0
- package/souls/default/rules.md +25 -0
- package/souls/default/soul.json +6 -0
- package/souls/young/rules.md +67 -0
- 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":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC;;;GAGG;AACH,SAAS,aAAa,CAAC,WAAmB,EAAE,UAAmB;IAC7D,MAAM,IAAI,GAAqD,EAAE,CAAC;IAElE,wBAAwB;IACxB,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,sBAAsB;IACtB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAC9D,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,yCAAyC;IACzC,IAAI,UAAU,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,GAAW,EAAE,MAAwB;IACvD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;QAC5D,IACE,CAAC,GAAG;YACJ,OAAO,GAAG,KAAK,QAAQ;YACvB,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAC5B,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;YACnC,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;YACnC,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;YAC/B,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAC5B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,GAAqB,CAAC;QAEvC,MAAM,oBAAoB,GAAG,OAAO,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAClE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAEnD,MAAM,gBAAgB,GAAG,UAAU,CAAC,oBAAoB,CAAC;YACvD,CAAC,CAAC,YAAY,CAAC,oBAAoB,EAAE,OAAO,CAAC;YAC7C,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,eAAe,GAAG,UAAU,CAAC,aAAa,CAAC;YAC/C,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC;YACtC,CAAC,CAAC,EAAE,CAAC;QAEP,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC3C,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC3C,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,YAAY,CAC7C,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,EACzB,OAAO,CACR,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QAC3D,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;QAE7C,OAAO;YACL,QAAQ;YACR,gBAAgB;YAChB,eAAe;YACf,OAAO;YACP,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;YACrC,QAAQ;SACT,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,WAAmB,EAAE,UAAmB;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1C,kEAAkE;IAClE,MAAM,IAAI,GAAG,aAAa,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;IAE9D,KAAK,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC/B,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACzC,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,WAAmB,EAAE,UAAmB;IAC9E,OAAO,WAAW,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AAC5F,CAAC"}
|
|
@@ -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
|