@pellux/goodvibes-sdk 0.26.10 → 0.27.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 (115) hide show
  1. package/dist/_internal/contracts/artifacts/operator-contract.json +4351 -5
  2. package/dist/_internal/contracts/generated/foundation-metadata.d.ts +2 -2
  3. package/dist/_internal/contracts/generated/foundation-metadata.js +2 -2
  4. package/dist/_internal/contracts/generated/operator-contract.d.ts.map +1 -1
  5. package/dist/_internal/contracts/generated/operator-contract.js +4351 -5
  6. package/dist/_internal/contracts/generated/operator-method-ids.d.ts +1 -1
  7. package/dist/_internal/contracts/generated/operator-method-ids.d.ts.map +1 -1
  8. package/dist/_internal/contracts/generated/operator-method-ids.js +10 -0
  9. package/dist/_internal/daemon/context.d.ts +1 -0
  10. package/dist/_internal/daemon/context.d.ts.map +1 -1
  11. package/dist/_internal/daemon/knowledge-route-types.d.ts +2 -1
  12. package/dist/_internal/daemon/knowledge-route-types.d.ts.map +1 -1
  13. package/dist/_internal/daemon/knowledge-routes.d.ts +1 -1
  14. package/dist/_internal/daemon/knowledge-routes.d.ts.map +1 -1
  15. package/dist/_internal/daemon/knowledge-routes.js +19 -3
  16. package/dist/_internal/daemon/operator.d.ts +1 -1
  17. package/dist/_internal/daemon/operator.d.ts.map +1 -1
  18. package/dist/_internal/daemon/operator.js +2 -0
  19. package/dist/_internal/platform/control-plane/method-catalog-homegraph.d.ts.map +1 -1
  20. package/dist/_internal/platform/control-plane/method-catalog-homegraph.js +12 -2
  21. package/dist/_internal/platform/control-plane/method-catalog-knowledge.d.ts.map +1 -1
  22. package/dist/_internal/platform/control-plane/method-catalog-knowledge.js +117 -1
  23. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts +3 -0
  24. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.d.ts.map +1 -1
  25. package/dist/_internal/platform/control-plane/operator-contract-schemas-knowledge.js +48 -3
  26. package/dist/_internal/platform/control-plane/operator-contract-schemas-project-planning.d.ts +8 -0
  27. package/dist/_internal/platform/control-plane/operator-contract-schemas-project-planning.d.ts.map +1 -0
  28. package/dist/_internal/platform/control-plane/operator-contract-schemas-project-planning.js +135 -0
  29. package/dist/_internal/platform/control-plane/routes/operator.d.ts +1 -1
  30. package/dist/_internal/platform/control-plane/routes/operator.d.ts.map +1 -1
  31. package/dist/_internal/platform/control-plane/routes/operator.js +2 -0
  32. package/dist/_internal/platform/daemon/facade-composition.d.ts.map +1 -1
  33. package/dist/_internal/platform/daemon/facade-composition.js +2 -0
  34. package/dist/_internal/platform/daemon/facade-types.d.ts +2 -1
  35. package/dist/_internal/platform/daemon/facade-types.d.ts.map +1 -1
  36. package/dist/_internal/platform/daemon/http/home-graph-routes.d.ts.map +1 -1
  37. package/dist/_internal/platform/daemon/http/home-graph-routes.js +21 -0
  38. package/dist/_internal/platform/daemon/http/project-planning-routes.d.ts +18 -0
  39. package/dist/_internal/platform/daemon/http/project-planning-routes.d.ts.map +1 -0
  40. package/dist/_internal/platform/daemon/http/project-planning-routes.js +68 -0
  41. package/dist/_internal/platform/daemon/http/router-route-contexts.d.ts.map +1 -1
  42. package/dist/_internal/platform/daemon/http/router-route-contexts.js +1 -0
  43. package/dist/_internal/platform/daemon/http/router.d.ts +4 -1
  44. package/dist/_internal/platform/daemon/http/router.d.ts.map +1 -1
  45. package/dist/_internal/platform/daemon/http/router.js +18 -0
  46. package/dist/_internal/platform/daemon/types.d.ts +2 -1
  47. package/dist/_internal/platform/daemon/types.d.ts.map +1 -1
  48. package/dist/_internal/platform/knowledge/generated-projections.d.ts +38 -0
  49. package/dist/_internal/platform/knowledge/generated-projections.d.ts.map +1 -0
  50. package/dist/_internal/platform/knowledge/generated-projections.js +106 -0
  51. package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts +29 -0
  52. package/dist/_internal/platform/knowledge/home-graph/generated-pages.d.ts.map +1 -0
  53. package/dist/_internal/platform/knowledge/home-graph/generated-pages.js +296 -0
  54. package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts +4 -1
  55. package/dist/_internal/platform/knowledge/home-graph/helpers.d.ts.map +1 -1
  56. package/dist/_internal/platform/knowledge/home-graph/helpers.js +21 -2
  57. package/dist/_internal/platform/knowledge/home-graph/index.d.ts +1 -1
  58. package/dist/_internal/platform/knowledge/home-graph/index.d.ts.map +1 -1
  59. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts +5 -0
  60. package/dist/_internal/platform/knowledge/home-graph/rendering.d.ts.map +1 -1
  61. package/dist/_internal/platform/knowledge/home-graph/rendering.js +32 -11
  62. package/dist/_internal/platform/knowledge/home-graph/search.d.ts.map +1 -1
  63. package/dist/_internal/platform/knowledge/home-graph/search.js +95 -11
  64. package/dist/_internal/platform/knowledge/home-graph/service.d.ts +2 -2
  65. package/dist/_internal/platform/knowledge/home-graph/service.d.ts.map +1 -1
  66. package/dist/_internal/platform/knowledge/home-graph/service.js +46 -93
  67. package/dist/_internal/platform/knowledge/home-graph/space-selection.d.ts +7 -0
  68. package/dist/_internal/platform/knowledge/home-graph/space-selection.d.ts.map +1 -0
  69. package/dist/_internal/platform/knowledge/home-graph/space-selection.js +36 -0
  70. package/dist/_internal/platform/knowledge/home-graph/types.d.ts +33 -2
  71. package/dist/_internal/platform/knowledge/home-graph/types.d.ts.map +1 -1
  72. package/dist/_internal/platform/knowledge/home-graph/types.js +2 -0
  73. package/dist/_internal/platform/knowledge/index.d.ts +9 -3
  74. package/dist/_internal/platform/knowledge/index.d.ts.map +1 -1
  75. package/dist/_internal/platform/knowledge/index.js +4 -1
  76. package/dist/_internal/platform/knowledge/knowledge-api.d.ts +2 -0
  77. package/dist/_internal/platform/knowledge/knowledge-api.d.ts.map +1 -1
  78. package/dist/_internal/platform/knowledge/knowledge-api.js +1 -0
  79. package/dist/_internal/platform/knowledge/map.d.ts +18 -0
  80. package/dist/_internal/platform/knowledge/map.d.ts.map +1 -0
  81. package/dist/_internal/platform/knowledge/map.js +235 -0
  82. package/dist/_internal/platform/knowledge/project-planning/helpers.d.ts +17 -0
  83. package/dist/_internal/platform/knowledge/project-planning/helpers.d.ts.map +1 -0
  84. package/dist/_internal/platform/knowledge/project-planning/helpers.js +65 -0
  85. package/dist/_internal/platform/knowledge/project-planning/index.d.ts +6 -0
  86. package/dist/_internal/platform/knowledge/project-planning/index.d.ts.map +1 -0
  87. package/dist/_internal/platform/knowledge/project-planning/index.js +3 -0
  88. package/dist/_internal/platform/knowledge/project-planning/readiness.d.ts +3 -0
  89. package/dist/_internal/platform/knowledge/project-planning/readiness.d.ts.map +1 -0
  90. package/dist/_internal/platform/knowledge/project-planning/readiness.js +124 -0
  91. package/dist/_internal/platform/knowledge/project-planning/service.d.ts +25 -0
  92. package/dist/_internal/platform/knowledge/project-planning/service.d.ts.map +1 -0
  93. package/dist/_internal/platform/knowledge/project-planning/service.js +259 -0
  94. package/dist/_internal/platform/knowledge/project-planning/types.d.ts +203 -0
  95. package/dist/_internal/platform/knowledge/project-planning/types.d.ts.map +1 -0
  96. package/dist/_internal/platform/knowledge/project-planning/types.js +1 -0
  97. package/dist/_internal/platform/knowledge/projection-utils.d.ts +16 -0
  98. package/dist/_internal/platform/knowledge/projection-utils.d.ts.map +1 -0
  99. package/dist/_internal/platform/knowledge/projection-utils.js +48 -0
  100. package/dist/_internal/platform/knowledge/projections.d.ts +1 -0
  101. package/dist/_internal/platform/knowledge/projections.d.ts.map +1 -1
  102. package/dist/_internal/platform/knowledge/projections.js +52 -58
  103. package/dist/_internal/platform/knowledge/service.d.ts +7 -1
  104. package/dist/_internal/platform/knowledge/service.d.ts.map +1 -1
  105. package/dist/_internal/platform/knowledge/service.js +11 -0
  106. package/dist/_internal/platform/knowledge/spaces.d.ts +4 -0
  107. package/dist/_internal/platform/knowledge/spaces.d.ts.map +1 -1
  108. package/dist/_internal/platform/knowledge/spaces.js +10 -0
  109. package/dist/_internal/platform/knowledge/types.d.ts +35 -0
  110. package/dist/_internal/platform/knowledge/types.d.ts.map +1 -1
  111. package/dist/_internal/platform/runtime/services.d.ts +2 -1
  112. package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
  113. package/dist/_internal/platform/runtime/services.js +5 -1
  114. package/dist/_internal/platform/version.js +1 -1
  115. package/package.json +1 -1
@@ -0,0 +1,235 @@
1
+ import { isGeneratedKnowledgeSource, } from './generated-projections.js';
2
+ export function renderKnowledgeMap(state, options = {}) {
3
+ const limit = sanitizeMapLimit(options.limit);
4
+ const nodes = state.nodes
5
+ .filter((node) => node.status !== 'stale')
6
+ .sort(compareRecordTitle)
7
+ .slice(0, limit);
8
+ let remaining = Math.max(0, limit - nodes.length);
9
+ const sources = options.includeSources === false
10
+ ? []
11
+ : state.sources
12
+ .filter((source) => source.status !== 'stale')
13
+ .filter((source) => options.includeGenerated !== false || !isGeneratedKnowledgeSource(source))
14
+ .sort(compareRecordTitle)
15
+ .slice(0, remaining);
16
+ remaining = Math.max(0, remaining - sources.length);
17
+ const issues = options.includeIssues
18
+ ? (state.issues ?? [])
19
+ .filter((issue) => issue.status === 'open')
20
+ .sort(compareIssue)
21
+ .slice(0, remaining)
22
+ : [];
23
+ const mapNodes = layoutMapNodes([
24
+ ...nodes.map((node) => ({
25
+ id: node.id,
26
+ recordKind: 'node',
27
+ kind: node.kind,
28
+ title: node.title,
29
+ ...(node.summary ? { summary: node.summary } : {}),
30
+ x: 0,
31
+ y: 0,
32
+ radius: radiusForNodeKind(node.kind),
33
+ metadata: node.metadata,
34
+ })),
35
+ ...sources.map((source) => ({
36
+ id: source.id,
37
+ recordKind: 'source',
38
+ kind: sourceKind(source),
39
+ title: source.title ?? source.sourceUri ?? source.id,
40
+ ...(source.summary ? { summary: source.summary } : {}),
41
+ x: 0,
42
+ y: 0,
43
+ radius: 11,
44
+ metadata: source.metadata,
45
+ })),
46
+ ...issues.map((issue) => ({
47
+ id: issue.id,
48
+ recordKind: 'issue',
49
+ kind: issue.code,
50
+ title: issue.message,
51
+ x: 0,
52
+ y: 0,
53
+ radius: 10,
54
+ metadata: issue.metadata,
55
+ })),
56
+ ]);
57
+ const nodeIds = new Set(mapNodes.map((node) => node.id));
58
+ const visibleEdges = state.edges
59
+ .filter((edge) => nodeIds.has(edge.fromId) && nodeIds.has(edge.toId))
60
+ .map((edge) => ({
61
+ id: edge.id,
62
+ fromId: edge.fromId,
63
+ toId: edge.toId,
64
+ relation: edge.relation,
65
+ weight: edge.weight,
66
+ metadata: edge.metadata,
67
+ }));
68
+ const width = 1280;
69
+ const height = 920;
70
+ const title = options.title ?? state.title ?? 'Knowledge Map';
71
+ return {
72
+ ok: true,
73
+ ...(options.spaceId ? { spaceId: options.spaceId } : {}),
74
+ title,
75
+ generatedAt: Date.now(),
76
+ width,
77
+ height,
78
+ nodeCount: mapNodes.length,
79
+ edgeCount: visibleEdges.length,
80
+ nodes: mapNodes,
81
+ edges: visibleEdges,
82
+ svg: renderMapSvg({ width, height, title, nodes: mapNodes, edges: visibleEdges }),
83
+ };
84
+ }
85
+ function layoutMapNodes(nodes) {
86
+ const width = 1280;
87
+ const height = 920;
88
+ const centerX = width / 2;
89
+ const centerY = height / 2;
90
+ const groups = new Map();
91
+ for (const node of nodes) {
92
+ const ring = ringForKind(node.kind, node.recordKind);
93
+ const group = groups.get(ring);
94
+ if (group) {
95
+ group.push(node);
96
+ }
97
+ else {
98
+ groups.set(ring, [node]);
99
+ }
100
+ }
101
+ const laidOut = [];
102
+ for (const [ring, group] of [...groups.entries()].sort((left, right) => left[0] - right[0])) {
103
+ const radius = ring === 0 ? 0 : 110 + ring * 90;
104
+ const offset = ring * 0.41;
105
+ group.forEach((node, index) => {
106
+ const angle = group.length === 1
107
+ ? -Math.PI / 2 + offset
108
+ : -Math.PI / 2 + offset + (Math.PI * 2 * index) / group.length;
109
+ laidOut.push({
110
+ ...node,
111
+ x: Math.round(centerX + Math.cos(angle) * radius),
112
+ y: Math.round(centerY + Math.sin(angle) * radius),
113
+ });
114
+ });
115
+ }
116
+ return laidOut;
117
+ }
118
+ function renderMapSvg(input) {
119
+ const byId = new Map(input.nodes.map((node) => [node.id, node]));
120
+ const edgeLines = input.edges.map((edge) => {
121
+ const from = byId.get(edge.fromId);
122
+ const to = byId.get(edge.toId);
123
+ if (!from || !to)
124
+ return '';
125
+ return `<line x1="${from.x}" y1="${from.y}" x2="${to.x}" y2="${to.y}" stroke="rgba(57,74,97,0.35)" stroke-width="1.3"><title>${escapeXml(edge.relation)}</title></line>`;
126
+ }).join('\n');
127
+ const nodeShapes = input.nodes.map((node) => {
128
+ const color = colorForKind(node.kind, node.recordKind);
129
+ const label = truncateLabel(node.title, node.recordKind === 'source' ? 28 : 24);
130
+ const shape = node.recordKind === 'source'
131
+ ? `<rect x="${node.x - 58}" y="${node.y - 17}" width="116" height="34" rx="11" fill="${color.fill}" stroke="${color.stroke}" stroke-width="1.4" />`
132
+ : `<circle cx="${node.x}" cy="${node.y}" r="${node.radius}" fill="${color.fill}" stroke="${color.stroke}" stroke-width="1.6" />`;
133
+ const textY = node.recordKind === 'source' ? node.y + 4 : node.y + node.radius + 18;
134
+ return `<g class="node">
135
+ <title>${escapeXml(node.title)} (${escapeXml(node.kind)})</title>
136
+ ${shape}
137
+ <text x="${node.x}" y="${textY}" text-anchor="middle">${escapeXml(label)}</text>
138
+ </g>`;
139
+ }).join('\n');
140
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${input.width}" height="${input.height}" viewBox="0 0 ${input.width} ${input.height}" role="img" aria-label="${escapeXml(input.title)}">
141
+ <defs>
142
+ <radialGradient id="knowledgeMapBg" cx="50%" cy="46%" r="70%">
143
+ <stop offset="0%" stop-color="#f7f4ec" />
144
+ <stop offset="60%" stop-color="#e9eef0" />
145
+ <stop offset="100%" stop-color="#dde6df" />
146
+ </radialGradient>
147
+ <filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
148
+ <feDropShadow dx="0" dy="6" stdDeviation="8" flood-color="#27313a" flood-opacity="0.14"/>
149
+ </filter>
150
+ </defs>
151
+ <style>
152
+ text { font-family: "Avenir Next", "Trebuchet MS", sans-serif; font-size: 12px; fill: #263238; paint-order: stroke; stroke: rgba(247,244,236,0.76); stroke-width: 3px; stroke-linejoin: round; }
153
+ .node { filter: url(#softShadow); }
154
+ </style>
155
+ <rect width="100%" height="100%" fill="url(#knowledgeMapBg)" />
156
+ <g>${edgeLines}</g>
157
+ <g>${nodeShapes}</g>
158
+ </svg>`;
159
+ }
160
+ function sourceKind(source) {
161
+ if (isGeneratedKnowledgeSource(source)) {
162
+ const projectionKind = typeof source.metadata.projectionKind === 'string'
163
+ ? source.metadata.projectionKind
164
+ : 'page';
165
+ return `generated_${projectionKind.replace(/[^a-z0-9]+/gi, '_')}`;
166
+ }
167
+ return source.sourceType;
168
+ }
169
+ function ringForKind(kind, recordKind) {
170
+ if (recordKind === 'issue')
171
+ return 7;
172
+ if (recordKind === 'source')
173
+ return kind.startsWith('generated_') ? 5 : 6;
174
+ if (kind === 'ha_home')
175
+ return 0;
176
+ if (kind === 'domain' || kind === 'topic' || kind === 'ha_area' || kind === 'ha_room')
177
+ return 1;
178
+ if (kind === 'ha_device' || kind === 'ha_device_passport')
179
+ return 2;
180
+ if (kind === 'ha_entity')
181
+ return 3;
182
+ return 4;
183
+ }
184
+ function radiusForNodeKind(kind) {
185
+ if (kind === 'ha_home' || kind === 'domain')
186
+ return 30;
187
+ if (kind === 'topic' || kind === 'ha_area' || kind === 'ha_room')
188
+ return 23;
189
+ if (kind === 'ha_device')
190
+ return 18;
191
+ if (kind === 'ha_entity')
192
+ return 13;
193
+ return 12;
194
+ }
195
+ function colorForKind(kind, recordKind) {
196
+ if (recordKind === 'issue')
197
+ return { fill: '#f4c7c3', stroke: '#9f3f36' };
198
+ if (recordKind === 'source') {
199
+ if (kind.startsWith('generated_'))
200
+ return { fill: '#fff1c7', stroke: '#b98920' };
201
+ return { fill: '#dceef5', stroke: '#3f839c' };
202
+ }
203
+ if (kind === 'ha_home' || kind === 'domain')
204
+ return { fill: '#284b63', stroke: '#102a3a' };
205
+ if (kind === 'topic' || kind === 'ha_area' || kind === 'ha_room')
206
+ return { fill: '#9ec5ab', stroke: '#49765a' };
207
+ if (kind === 'ha_device')
208
+ return { fill: '#f2b880', stroke: '#a86028' };
209
+ if (kind === 'ha_entity')
210
+ return { fill: '#b8c7e0', stroke: '#5d7092' };
211
+ if (kind === 'ha_device_passport')
212
+ return { fill: '#f6df90', stroke: '#9a7725' };
213
+ return { fill: '#d7d0c2', stroke: '#70695e' };
214
+ }
215
+ function compareRecordTitle(left, right) {
216
+ return (left.title ?? left.id).localeCompare(right.title ?? right.id) || left.id.localeCompare(right.id);
217
+ }
218
+ function compareIssue(left, right) {
219
+ return left.code.localeCompare(right.code) || left.id.localeCompare(right.id);
220
+ }
221
+ function sanitizeMapLimit(value) {
222
+ if (typeof value !== 'number' || !Number.isFinite(value))
223
+ return 500;
224
+ return Math.max(1, Math.min(1000, Math.trunc(value)));
225
+ }
226
+ function truncateLabel(value, limit) {
227
+ return value.length <= limit ? value : `${value.slice(0, Math.max(1, limit - 1))}...`;
228
+ }
229
+ function escapeXml(value) {
230
+ return value
231
+ .replaceAll('&', '&amp;')
232
+ .replaceAll('<', '&lt;')
233
+ .replaceAll('>', '&gt;')
234
+ .replaceAll('"', '&quot;');
235
+ }
@@ -0,0 +1,17 @@
1
+ import type { ProjectPlanningSpaceInput } from './types.js';
2
+ export declare const PROJECT_PLANNING_CONNECTOR_ID = "goodvibes-project-planning";
3
+ export declare const PROJECT_PLANNING_TAG = "project-planning";
4
+ export type ProjectPlanningArtifactKind = 'state' | 'decision' | 'language';
5
+ export interface ResolvedProjectPlanningSpace {
6
+ readonly projectId: string;
7
+ readonly knowledgeSpaceId: string;
8
+ }
9
+ export declare function projectPlanningProjectIdFromPath(path: string): string;
10
+ export declare function resolveProjectPlanningSpace(input?: ProjectPlanningSpaceInput, defaultProjectId?: string): ResolvedProjectPlanningSpace;
11
+ export declare function projectIdFromSpace(spaceId: string): string;
12
+ export declare function projectPlanningCanonicalUri(spaceId: string, kind: ProjectPlanningArtifactKind, id: string): string;
13
+ export declare function projectPlanningSourceId(spaceId: string, kind: ProjectPlanningArtifactKind, id: string): string;
14
+ export declare function projectPlanningArtifactSummary(kind: ProjectPlanningArtifactKind, value: unknown): string;
15
+ export declare function stablePlanningId(prefix: string, value: string): string;
16
+ export declare function readPlanningMetadataObject(value: unknown): Record<string, unknown>;
17
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/project-planning/helpers.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAGV,yBAAyB,EAE1B,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,6BAA6B,+BAA+B,CAAC;AAC1E,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AAEvD,MAAM,MAAM,2BAA2B,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrE;AAED,wBAAgB,2BAA2B,CACzC,KAAK,GAAE,yBAA8B,EACrC,gBAAgB,SAAY,GAC3B,4BAA4B,CAe9B;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,2BAA2B,EACjC,EAAE,EAAE,MAAM,GACT,MAAM,CAER;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,2BAA2B,EACjC,EAAE,EAAE,MAAM,GACT,MAAM,CAGR;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,2BAA2B,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAWxG;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIlF"}
@@ -0,0 +1,65 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { basename, resolve } from 'node:path';
3
+ import { PROJECT_KNOWLEDGE_SPACE_PREFIX, isProjectKnowledgeSpace, normalizeKnowledgeSpaceId, normalizeProjectId, normalizeSpaceComponent, projectKnowledgeSpaceId, } from '../spaces.js';
4
+ export const PROJECT_PLANNING_CONNECTOR_ID = 'goodvibes-project-planning';
5
+ export const PROJECT_PLANNING_TAG = 'project-planning';
6
+ export function projectPlanningProjectIdFromPath(path) {
7
+ const resolved = resolve(path);
8
+ const name = normalizeSpaceComponent(basename(resolved) || 'project');
9
+ const digest = createHash('sha256').update(resolved).digest('hex').slice(0, 10);
10
+ return `${name}-${digest}`;
11
+ }
12
+ export function resolveProjectPlanningSpace(input = {}, defaultProjectId = 'default') {
13
+ const explicitSpace = typeof input.knowledgeSpaceId === 'string'
14
+ ? normalizeKnowledgeSpaceId(input.knowledgeSpaceId)
15
+ : '';
16
+ if (explicitSpace && isProjectKnowledgeSpace(explicitSpace)) {
17
+ return {
18
+ knowledgeSpaceId: explicitSpace,
19
+ projectId: projectIdFromSpace(explicitSpace),
20
+ };
21
+ }
22
+ const projectId = normalizeProjectId(input.projectId ?? defaultProjectId);
23
+ return {
24
+ projectId,
25
+ knowledgeSpaceId: projectKnowledgeSpaceId(projectId),
26
+ };
27
+ }
28
+ export function projectIdFromSpace(spaceId) {
29
+ const normalized = normalizeKnowledgeSpaceId(spaceId);
30
+ if (!normalized.startsWith(PROJECT_KNOWLEDGE_SPACE_PREFIX)) {
31
+ return normalizeProjectId(normalized);
32
+ }
33
+ return normalizeProjectId(normalized.slice(PROJECT_KNOWLEDGE_SPACE_PREFIX.length));
34
+ }
35
+ export function projectPlanningCanonicalUri(spaceId, kind, id) {
36
+ return `goodvibes://planning/${encodeURIComponent(spaceId)}/${kind}/${encodeURIComponent(id)}`;
37
+ }
38
+ export function projectPlanningSourceId(spaceId, kind, id) {
39
+ const digest = createHash('sha256').update(`${spaceId}:${kind}:${id}`).digest('hex').slice(0, 16);
40
+ return `project-planning-${kind}-${digest}`;
41
+ }
42
+ export function projectPlanningArtifactSummary(kind, value) {
43
+ if (kind === 'state') {
44
+ const state = value;
45
+ return state.goal ? `Planning state for ${state.goal}` : 'Project planning state.';
46
+ }
47
+ if (kind === 'decision') {
48
+ const decision = value;
49
+ return decision.decision ? `${decision.title ?? 'Decision'}: ${decision.decision}` : 'Project planning decision record.';
50
+ }
51
+ const language = value;
52
+ return `Project language artifact with ${language.terms?.length ?? 0} terms and ${language.ambiguities?.length ?? 0} resolved ambiguities.`;
53
+ }
54
+ export function stablePlanningId(prefix, value) {
55
+ const normalized = normalizeSpaceComponent(value);
56
+ if (normalized !== 'default')
57
+ return normalized;
58
+ const digest = createHash('sha256').update(value || prefix).digest('hex').slice(0, 10);
59
+ return `${prefix}-${digest}`;
60
+ }
61
+ export function readPlanningMetadataObject(value) {
62
+ return value && typeof value === 'object' && !Array.isArray(value)
63
+ ? value
64
+ : {};
65
+ }
@@ -0,0 +1,6 @@
1
+ export { ProjectPlanningService } from './service.js';
2
+ export type { ProjectPlanningServiceOptions } from './service.js';
3
+ export { PROJECT_PLANNING_CONNECTOR_ID, PROJECT_PLANNING_TAG, projectPlanningCanonicalUri, projectPlanningProjectIdFromPath, projectPlanningSourceId, resolveProjectPlanningSpace, } from './helpers.js';
4
+ export { evaluateProjectPlanningReadiness } from './readiness.js';
5
+ export type { ProjectPlanningAgentAssignment, ProjectPlanningAmbiguity, ProjectPlanningDecision, ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningDecisionStatus, ProjectPlanningDependency, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningGap, ProjectPlanningGapKind, ProjectPlanningGapSeverity, ProjectPlanningGateStatus, ProjectPlanningLanguageArtifact, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningQuestion, ProjectPlanningQuestionStatus, ProjectPlanningReadiness, ProjectPlanningSpaceInput, ProjectPlanningState, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus, ProjectPlanningTask, ProjectPlanningTaskStatus, ProjectPlanningTerm, ProjectPlanningVerificationGate, } from './types.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/project-planning/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EACL,6BAA6B,EAC7B,oBAAoB,EACpB,2BAA2B,EAC3B,gCAAgC,EAChC,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,kCAAkC,EAClC,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,EAC/B,6BAA6B,EAC7B,kCAAkC,EAClC,uBAAuB,EACvB,6BAA6B,EAC7B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { ProjectPlanningService } from './service.js';
2
+ export { PROJECT_PLANNING_CONNECTOR_ID, PROJECT_PLANNING_TAG, projectPlanningCanonicalUri, projectPlanningProjectIdFromPath, projectPlanningSourceId, resolveProjectPlanningSpace, } from './helpers.js';
3
+ export { evaluateProjectPlanningReadiness } from './readiness.js';
@@ -0,0 +1,3 @@
1
+ import type { ProjectPlanningEvaluation, ProjectPlanningState } from './types.js';
2
+ export declare function evaluateProjectPlanningReadiness(state: ProjectPlanningState): ProjectPlanningEvaluation;
3
+ //# sourceMappingURL=readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/project-planning/readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EAIzB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAiBpB,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,oBAAoB,GAAG,yBAAyB,CA2GvG"}
@@ -0,0 +1,124 @@
1
+ const VAGUE_TERMS = [
2
+ 'better',
3
+ 'improve',
4
+ 'improved',
5
+ 'setup',
6
+ 'integration',
7
+ 'agent channel',
8
+ 'remote',
9
+ 'thing',
10
+ 'stuff',
11
+ 'etc',
12
+ 'clean up',
13
+ 'fix it',
14
+ ];
15
+ export function evaluateProjectPlanningReadiness(state) {
16
+ const gaps = [];
17
+ const goal = state.goal.trim();
18
+ if (!goal) {
19
+ gaps.push(blockingQuestion('missing-goal', 'The plan needs a concrete goal before it can be executed.', 'What outcome should this plan produce?', 'A clear outcome lets the TUI inspect the right code and ask only relevant follow-up questions.', 'State the user-visible behavior or project change that should exist when the work is done.'));
20
+ }
21
+ if (!state.scope?.trim() && state.constraints.length === 0) {
22
+ gaps.push(blockingQuestion('missing-scope', 'The plan has no explicit boundary for what is included or excluded.', 'What is in scope, and what should be left out for this pass?', 'Scope boundaries prevent the planning loop from turning a focused change into unrelated work.', 'Define the first-pass scope and record do-later items separately.'));
23
+ }
24
+ for (const question of state.openQuestions) {
25
+ if ((question.status ?? 'open') === 'open') {
26
+ gaps.push({
27
+ id: `open-question:${question.id}`,
28
+ kind: 'open-question',
29
+ severity: 'blocking',
30
+ message: `Open planning question: ${question.prompt}`,
31
+ question,
32
+ });
33
+ }
34
+ }
35
+ const vagueTerm = firstVagueTerm(goal);
36
+ if (vagueTerm && state.answeredQuestions.length === 0 && state.decisions.length === 0) {
37
+ gaps.push(blockingQuestion('ambiguous-language', `The goal uses ambiguous language (${JSON.stringify(vagueTerm)}) without recorded clarification.`, `When you say ${JSON.stringify(vagueTerm)}, what concrete behavior should change?`, 'GoodVibes should challenge vague words before work starts so future agents do not implement the wrong thing.', 'Define the term in project language or replace it with concrete expected behavior.'));
38
+ }
39
+ if (goal && state.tasks.length === 0) {
40
+ gaps.push(blockingQuestion('missing-tasks', 'The plan has no decomposed tasks.', 'What are the smallest useful implementation tasks for this goal?', 'Task decomposition is what lets the TUI identify dependencies, parallel agent work, and verification gates.', 'Create task records with likely files, dependencies, and verification notes.'));
41
+ }
42
+ if (state.tasks.length > 1 && state.dependencies.length === 0) {
43
+ gaps.push({
44
+ id: 'missing-dependencies',
45
+ kind: 'missing-dependencies',
46
+ severity: 'advisory',
47
+ message: 'Multiple tasks exist but no dependency graph has been recorded.',
48
+ });
49
+ }
50
+ const tasksWithoutVerification = state.tasks
51
+ .filter((task) => (task.verification?.length ?? 0) === 0)
52
+ .map((task) => task.id);
53
+ const hasRequiredGate = state.verificationGates.some((gate) => gate.required !== false);
54
+ if (state.tasks.length > 0 && tasksWithoutVerification.length > 0 && !hasRequiredGate) {
55
+ gaps.push({
56
+ id: 'missing-verification',
57
+ kind: 'missing-verification',
58
+ severity: 'blocking',
59
+ message: 'The plan has tasks but no verification gates or per-task verification.',
60
+ question: {
61
+ id: 'verification-gates',
62
+ prompt: 'How should this plan prove that the work is correct?',
63
+ whyItMatters: 'Verification gates keep execution from ending at code changes that were never checked.',
64
+ recommendedAnswer: 'Record concrete tests, commands, manual checks, or release gates for the changed behavior.',
65
+ consequence: 'The plan should not be executable until verification exists.',
66
+ },
67
+ relatedTaskIds: tasksWithoutVerification,
68
+ });
69
+ }
70
+ const blocking = gaps.some((gap) => gap.severity === 'blocking');
71
+ if (!blocking && !state.executionApproved) {
72
+ gaps.push({
73
+ id: 'unapproved-execution',
74
+ kind: 'unapproved-execution',
75
+ severity: 'blocking',
76
+ message: 'The plan is structurally ready but has not been approved for execution.',
77
+ question: {
78
+ id: 'approve-execution',
79
+ prompt: 'Is this plan approved for execution?',
80
+ whyItMatters: 'The TUI owns user approval before local work or agent assignments begin.',
81
+ recommendedAnswer: 'Approve only after the goal, scope, tasks, dependencies, and verification gates look right.',
82
+ },
83
+ });
84
+ }
85
+ const readiness = readinessFromGaps(gaps);
86
+ return {
87
+ ok: true,
88
+ projectId: state.projectId,
89
+ knowledgeSpaceId: state.knowledgeSpaceId,
90
+ readiness,
91
+ gaps,
92
+ ...(gaps[0]?.question ? { nextQuestion: gaps[0].question } : {}),
93
+ state: {
94
+ ...state,
95
+ readiness,
96
+ },
97
+ };
98
+ }
99
+ function readinessFromGaps(gaps) {
100
+ if (gaps.length === 0)
101
+ return 'executable';
102
+ if (gaps.some((gap) => gap.severity === 'blocking'))
103
+ return 'needs-user-input';
104
+ return 'not-ready';
105
+ }
106
+ function firstVagueTerm(value) {
107
+ const normalized = value.toLowerCase();
108
+ return VAGUE_TERMS.find((term) => normalized.includes(term)) ?? null;
109
+ }
110
+ function blockingQuestion(kind, message, prompt, whyItMatters, recommendedAnswer) {
111
+ const question = {
112
+ id: kind,
113
+ prompt,
114
+ whyItMatters,
115
+ recommendedAnswer,
116
+ };
117
+ return {
118
+ id: kind,
119
+ kind,
120
+ severity: 'blocking',
121
+ message,
122
+ question,
123
+ };
124
+ }
@@ -0,0 +1,25 @@
1
+ import { KnowledgeStore } from '../store.js';
2
+ import type { ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningSpaceInput, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus } from './types.js';
3
+ export interface ProjectPlanningServiceOptions {
4
+ readonly defaultProjectId?: string;
5
+ }
6
+ export declare class ProjectPlanningService {
7
+ private readonly store;
8
+ private readonly defaultProjectId;
9
+ constructor(store: KnowledgeStore, options?: ProjectPlanningServiceOptions);
10
+ status(input?: ProjectPlanningSpaceInput): Promise<ProjectPlanningStatus>;
11
+ getState(input?: ProjectPlanningSpaceInput & {
12
+ readonly planningId?: string;
13
+ }): Promise<ProjectPlanningStateResult>;
14
+ upsertState(input: ProjectPlanningStateUpsertInput): Promise<ProjectPlanningStateResult>;
15
+ evaluate(input?: ProjectPlanningEvaluateInput): Promise<ProjectPlanningEvaluation>;
16
+ listDecisions(input?: ProjectPlanningSpaceInput): Promise<ProjectPlanningDecisionsResult>;
17
+ recordDecision(input: ProjectPlanningDecisionRecordInput): Promise<ProjectPlanningDecisionResult>;
18
+ getLanguage(input?: ProjectPlanningSpaceInput): Promise<ProjectPlanningLanguageResult>;
19
+ upsertLanguage(input: ProjectPlanningLanguageUpsertInput): Promise<ProjectPlanningLanguageResult>;
20
+ private resolveSpace;
21
+ private sourcesForSpace;
22
+ private getArtifactSource;
23
+ private upsertArtifactSource;
24
+ }
25
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../src/_internal/platform/knowledge/project-planning/service.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C,OAAO,KAAK,EAEV,kCAAkC,EAClC,6BAA6B,EAC7B,8BAA8B,EAC9B,4BAA4B,EAC5B,yBAAyB,EAEzB,6BAA6B,EAC7B,kCAAkC,EAClC,yBAAyB,EAEzB,0BAA0B,EAC1B,+BAA+B,EAC/B,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,qBAAa,sBAAsB;IAI/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAGvB,KAAK,EAAE,cAAc,EACtC,OAAO,GAAE,6BAAkC;IAKvC,MAAM,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAyB7E,QAAQ,CAAC,KAAK,GAAE,yBAAyB,GAAG;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAevH,WAAW,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAgBxF,QAAQ,CAAC,KAAK,GAAE,4BAAiC,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAWtF,aAAa,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAgB7F,cAAc,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC;IA2BjG,WAAW,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,6BAA6B,CAAC;IAc1F,cAAc,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC;IA2BvG,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;YASX,oBAAoB;CAyBnC"}