@work-graph/cli 0.2.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.
- package/README.md +31 -0
- package/bin/work-graph.mjs +238 -0
- package/package.json +38 -0
- package/vendor/packages/design-tokens/generated/gripe-dark-default.css +67 -0
- package/vendor/packages/design-tokens/generated/marketplace-default.css +67 -0
- package/vendor/packages/design-tokens/generated/workgraph-dark.css +67 -0
- package/vendor/packages/workgraph-mcp/README.md +28 -0
- package/vendor/packages/workgraph-mcp/bin/workgraph-mcp.mjs +21 -0
- package/vendor/packages/workgraph-mcp/package.json +37 -0
- package/vendor/packages/workgraph-mcp/src/handlers.mjs +761 -0
- package/vendor/packages/workgraph-mcp/src/index.mjs +638 -0
- package/vendor/packages/workgraph-mcp/src/prompts.mjs +162 -0
- package/vendor/public/assets/workgraph-logo.svg +11 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Medium.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Regular.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/GraphikLCG-Semibold.woff2 +0 -0
- package/vendor/public/fonts/GraphikLCG/stylesheet.css +25 -0
- package/vendor/public/graph-canvas-lit-flow.css +154 -0
- package/vendor/public/graph-canvas-lit-flow.css.map +7 -0
- package/vendor/public/graph-canvas-lit-flow.js +8530 -0
- package/vendor/public/graph-canvas-lit-flow.js.map +7 -0
- package/vendor/src/agentBehaviorRulesAudit.mjs +168 -0
- package/vendor/src/agentBehaviorRulesBundle.mjs +144 -0
- package/vendor/src/agentRunApi.mjs +136 -0
- package/vendor/src/agentToolLoopGuard.mjs +88 -0
- package/vendor/src/agentWorkerClaudeProvider.mjs +288 -0
- package/vendor/src/agentWorkerCursorSdkProvider.mjs +156 -0
- package/vendor/src/agentWorkerLiveLoop.mjs +455 -0
- package/vendor/src/agentWorkerLocalCliProvider.mjs +217 -0
- package/vendor/src/agentWorkerLocalRunner.mjs +246 -0
- package/vendor/src/agentWorkerOpenAiProvider.mjs +459 -0
- package/vendor/src/analyticsPanelProjection.mjs +212 -0
- package/vendor/src/analyticsRecordStore.mjs +165 -0
- package/vendor/src/analyticsRecordWorkItems.mjs +104 -0
- package/vendor/src/architectureL1Canon.mjs +419 -0
- package/vendor/src/architectureLayout.mjs +229 -0
- package/vendor/src/architectureSnapshot.mjs +490 -0
- package/vendor/src/architectureViewsProjection.mjs +116 -0
- package/vendor/src/atomInspector.mjs +253 -0
- package/vendor/src/atomInspectorApi.mjs +130 -0
- package/vendor/src/auditGapMatrixRefresh.mjs +121 -0
- package/vendor/src/backlogSchemaLint.mjs +176 -0
- package/vendor/src/blockedOnebaseGoPreflightEval.mjs +100 -0
- package/vendor/src/bracketIrTraceSignal.mjs +93 -0
- package/vendor/src/bvcAtomParser.mjs +210 -0
- package/vendor/src/bvcDialectRegistry.mjs +86 -0
- package/vendor/src/bvcFileFormat.mjs +218 -0
- package/vendor/src/bvcFormatCli.mjs +55 -0
- package/vendor/src/bvcLintCli.mjs +48 -0
- package/vendor/src/bvcNewWritePolicy.mjs +70 -0
- package/vendor/src/charterPreflightPromoteGate.mjs +194 -0
- package/vendor/src/claimNoEligibleEval.mjs +205 -0
- package/vendor/src/closingAnalysisSuggest.mjs +59 -0
- package/vendor/src/codeGapAnalyzer.mjs +308 -0
- package/vendor/src/codeGapBacklogFeeder.mjs +82 -0
- package/vendor/src/codeGapDraftIntakeApi.mjs +307 -0
- package/vendor/src/codeGapOperatorProjection.mjs +60 -0
- package/vendor/src/codeSyntaxHighlight.mjs +123 -0
- package/vendor/src/codegenEvidence.mjs +187 -0
- package/vendor/src/compilerRoundTripCli.mjs +164 -0
- package/vendor/src/dagreGraphLayout.mjs +78 -0
- package/vendor/src/draftIntakePromotionRules.mjs +205 -0
- package/vendor/src/epicWorkScope.mjs +85 -0
- package/vendor/src/evalLiveLlmEnv.mjs +63 -0
- package/vendor/src/evidenceReadModel.mjs +167 -0
- package/vendor/src/gfsOverlayProjectPassport.mjs +235 -0
- package/vendor/src/globalStepPathToBvcReferences.mjs +196 -0
- package/vendor/src/goldenPath.mjs +69 -0
- package/vendor/src/graphCanvasLayout.mjs +464 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasMinimap.ts +261 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasSvgEdges.ts +259 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCanvasTheme.css +152 -0
- package/vendor/src/graphCanvasLitFlow/client/graphCardNode.ts +328 -0
- package/vendor/src/graphCanvasLitFlow/client/mountGraphCanvasLitFlow.ts +322 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeLabels.mjs +58 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasEdgeRouter.mjs +142 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasLayoutProfile.mjs +32 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasNodeMetrics.mjs +45 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasProjection.mjs +115 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasProjectionToFlow.mjs +133 -0
- package/vendor/src/graphCanvasLitFlow/graphCanvasTraversal.mjs +77 -0
- package/vendor/src/graphCanvasLitFlow/layoutIntentRoadmapWorkStack.mjs +73 -0
- package/vendor/src/graphCanvasLitFlow/resolveGraphCanvasOverlaps.mjs +77 -0
- package/vendor/src/graphRagContextSlice.mjs +461 -0
- package/vendor/src/gvmVerifyWorkerGate.mjs +95 -0
- package/vendor/src/homeSnapshotApi.mjs +131 -0
- package/vendor/src/homeSnapshotProjection.mjs +275 -0
- package/vendor/src/inboxEventStream.mjs +140 -0
- package/vendor/src/intentComposerApi.mjs +245 -0
- package/vendor/src/intentGraphGbcSliceBoundary.mjs +258 -0
- package/vendor/src/intentGraphProjection.mjs +208 -0
- package/vendor/src/intentHierarchy.mjs +241 -0
- package/vendor/src/intentNodeLint.mjs +107 -0
- package/vendor/src/intentNodeRuntime.mjs +185 -0
- package/vendor/src/intentRoadmapCanvas.mjs +393 -0
- package/vendor/src/intentRoadmapEpicProjection.mjs +122 -0
- package/vendor/src/intentRoadmapMermaid.mjs +165 -0
- package/vendor/src/intentRoadmapProjection.mjs +85 -0
- package/vendor/src/intentTreeLint.mjs +114 -0
- package/vendor/src/intentTreeMigration.mjs +150 -0
- package/vendor/src/intentTreeWorkItems.mjs +227 -0
- package/vendor/src/kanbanBoardProjection.mjs +58 -0
- package/vendor/src/languageAdapterRegistry.mjs +180 -0
- package/vendor/src/languageAdapters/goAdapter.mjs +62 -0
- package/vendor/src/languageAdapters/jsTsAdapter.mjs +60 -0
- package/vendor/src/languageAdapters/jsonYamlAdapter.mjs +103 -0
- package/vendor/src/languageAdapters/onebaseOsAdapter.mjs +55 -0
- package/vendor/src/languageAdapters/plaintextAdapter.mjs +36 -0
- package/vendor/src/languageAdapters/shared.mjs +68 -0
- package/vendor/src/languageAdapters/stepAdapter.mjs +81 -0
- package/vendor/src/lintPlanWorkAlignment.mjs +136 -0
- package/vendor/src/loopHintRepeatToolEval.mjs +153 -0
- package/vendor/src/lowcodeScaffoldCli.mjs +386 -0
- package/vendor/src/markdownDocumentRender.mjs +208 -0
- package/vendor/src/memoryPanelProjection.mjs +116 -0
- package/vendor/src/memoryRecordWriter.mjs +243 -0
- package/vendor/src/memoryWorkerSlice.mjs +238 -0
- package/vendor/src/migrateStepToBvc.mjs +133 -0
- package/vendor/src/missionControlServerHandlers.mjs +195 -0
- package/vendor/src/missionControlUiClient.mjs +278 -0
- package/vendor/src/onebaseCliCapabilityProbe.mjs +107 -0
- package/vendor/src/onebaseCliRunner.mjs +145 -0
- package/vendor/src/onebaseGrossProfitStaticVerify.mjs +98 -0
- package/vendor/src/onebaseParityEvidenceSync.mjs +88 -0
- package/vendor/src/onebasePvrgGraphNodes.mjs +257 -0
- package/vendor/src/onebaseRestEvidenceAdapter.mjs +216 -0
- package/vendor/src/onebaseVectorDslCodegenReadiness.mjs +137 -0
- package/vendor/src/onebaseWorkItemTemplate.mjs +154 -0
- package/vendor/src/onebaseWorkerTools.mjs +586 -0
- package/vendor/src/operatorShellProjection.mjs +102 -0
- package/vendor/src/pipelineProseRender.mjs +180 -0
- package/vendor/src/pipelineStageLint.mjs +118 -0
- package/vendor/src/promptRulesEditorApi.mjs +174 -0
- package/vendor/src/promptRulesProjection.mjs +134 -0
- package/vendor/src/pvrg/bladeAdapter.mjs +40 -0
- package/vendor/src/pvrgTaskScope.mjs +152 -0
- package/vendor/src/releaseGateMatrix.mjs +188 -0
- package/vendor/src/schematicView.mjs +305 -0
- package/vendor/src/seedAnalyticsRecord.mjs +217 -0
- package/vendor/src/semanticSearchBm25.mjs +103 -0
- package/vendor/src/semanticSearchExcerpts.mjs +68 -0
- package/vendor/src/semanticSearchTfidfVector.mjs +86 -0
- package/vendor/src/semanticSearchWorkflow.mjs +366 -0
- package/vendor/src/stepAtomFormatter.mjs +413 -0
- package/vendor/src/stepGraphSlice.mjs +318 -0
- package/vendor/src/ui/atoms/badge.mjs +40 -0
- package/vendor/src/ui/atoms/badgeClient.mjs +32 -0
- package/vendor/src/ui/atoms/button.mjs +114 -0
- package/vendor/src/ui/atoms/buttonClient.mjs +49 -0
- package/vendor/src/ui/atoms/icon.mjs +23 -0
- package/vendor/src/ui/atoms/input.mjs +38 -0
- package/vendor/src/ui/atoms/modal.mjs +44 -0
- package/vendor/src/ui/atoms/select.mjs +98 -0
- package/vendor/src/ui/backlogShellButtons.mjs +238 -0
- package/vendor/src/ui/htmlEscape.mjs +11 -0
- package/vendor/src/ui/molecules/rating.mjs +48 -0
- package/vendor/src/ui/molecules/tabs.mjs +70 -0
- package/vendor/src/ui/organisms/modal.mjs +1 -0
- package/vendor/src/ui/pages/uiKitPage.mjs +147 -0
- package/vendor/src/ui/workItemStatusTone.mjs +36 -0
- package/vendor/src/unifiedLinkageProjection.mjs +264 -0
- package/vendor/src/verificationLoop.mjs +206 -0
- package/vendor/src/workGraphBacklogPersist.mjs +234 -0
- package/vendor/src/workGraphBacklogUiServer.mjs +9192 -0
- package/vendor/src/workGraphBoundedTargetFileRead.mjs +178 -0
- package/vendor/src/workGraphCycleSlice.mjs +184 -0
- package/vendor/src/workGraphDaemonTick.mjs +307 -0
- package/vendor/src/workGraphDaemonWatch.mjs +157 -0
- package/vendor/src/workGraphEngineRoot.mjs +136 -0
- package/vendor/src/workGraphInstallLayout.mjs +65 -0
- package/vendor/src/workGraphLlmUsefulnessEval.mjs +611 -0
- package/vendor/src/workGraphPhasePromoteReadyQueue.mjs +159 -0
- package/vendor/src/workGraphProjectHost.mjs +149 -0
- package/vendor/src/workGraphProjectInit.mjs +392 -0
- package/vendor/src/workGraphPromoteReadyApi.mjs +115 -0
- package/vendor/src/workGraphRecoveryPolicy.mjs +124 -0
- package/vendor/src/workGraphRunnerQueueProjection.mjs +187 -0
- package/vendor/src/workGraphRuntime.mjs +1008 -0
- package/vendor/src/workGraphToolSurfaceAudit.mjs +372 -0
- package/vendor/src/workGraphToolTransportRuntime.mjs +195 -0
- package/vendor/src/workGraphWorkerProvider.mjs +600 -0
- package/vendor/src/workItemBvcQuality.mjs +262 -0
- package/vendor/src/workItemCreateAnalysis.mjs +157 -0
- package/vendor/src/workItemDecisionPipeline.mjs +278 -0
- package/vendor/src/workItemEpicCascade.mjs +176 -0
- package/vendor/src/workItemExecutionGate.mjs +78 -0
- package/vendor/src/workItemHierarchy.mjs +226 -0
- package/vendor/src/workItemProseLint.mjs +133 -0
- package/vendor/src/workItemTextRusify.mjs +794 -0
- package/vendor/src/workItemTraceEnvelope.mjs +158 -0
- package/vendor/src/workItemUiReferences.mjs +272 -0
- package/vendor/src/workflowEpicGrouping.mjs +67 -0
- package/vendor/src/workflowTreeProjection.mjs +53 -0
- package/vendor/src/workspaceRegistry.mjs +150 -0
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
import { buildGraphRagContextForWorkerInput, formatGraphRagContextForPrompt } from './graphRagContextSlice.mjs';
|
|
2
|
+
import { applyWorkerOutputToItem } from './agentWorkerLiveLoop.mjs';
|
|
3
|
+
import { runLocalWorker, buildWorkerInputFromTask } from './agentWorkerLocalRunner.mjs';
|
|
4
|
+
import { buildPromptEvalWorkGraphFixtureCatalog } from './workGraphToolSurfaceAudit.mjs';
|
|
5
|
+
import { parseWorkItems, transitionStatus } from './workGraphRuntime.mjs';
|
|
6
|
+
import { workgraphPrompts } from '../packages/workgraph-mcp/src/prompts.mjs';
|
|
7
|
+
|
|
8
|
+
export const LLM_USEFULNESS_EVAL_SCHEMA = 'workgraph.llm-usefulness.eval.v1';
|
|
9
|
+
|
|
10
|
+
export const MCP_READ_FIELDS_FOR_LLM = [
|
|
11
|
+
'id',
|
|
12
|
+
'title',
|
|
13
|
+
'status',
|
|
14
|
+
'targetFiles',
|
|
15
|
+
'dependsOn',
|
|
16
|
+
'nextAction',
|
|
17
|
+
'checks',
|
|
18
|
+
'evidence',
|
|
19
|
+
'blocker',
|
|
20
|
+
'ownerRole',
|
|
21
|
+
'priority',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const MCP_WRITE_TOOLS_V1 = [
|
|
25
|
+
'create_work_item',
|
|
26
|
+
'record_work_item_analysis',
|
|
27
|
+
'record_work_item_decision',
|
|
28
|
+
'update_work_item_status',
|
|
29
|
+
'add_work_item_evidence',
|
|
30
|
+
'claim_work_item',
|
|
31
|
+
'complete_work_item',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const MCP_INTENT_GRAPH_TOOLS_V1 = [
|
|
35
|
+
'get_intent_hierarchy',
|
|
36
|
+
'get_architecture_snapshot',
|
|
37
|
+
'get_unified_linkage',
|
|
38
|
+
'get_pvrg_task_scope',
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
export const MCP_CURSOR_CONTEXT_TOOLS_V1 = [
|
|
42
|
+
'get_graph_rag_context',
|
|
43
|
+
'list_memory_records',
|
|
44
|
+
'get_memory_record',
|
|
45
|
+
'list_evidence_records',
|
|
46
|
+
'get_evidence_record',
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export const DEFAULT_CONTEXT_BUDGET_CHARS = 12_000;
|
|
50
|
+
|
|
51
|
+
const compareText = (left, right) => String(left).localeCompare(String(right), 'en', { sensitivity: 'variant' });
|
|
52
|
+
|
|
53
|
+
const SAMPLE_READY_BACKLOG = `#Задача_done_dep<[
|
|
54
|
+
Базис:
|
|
55
|
+
Dependency done.
|
|
56
|
+
Вектор:
|
|
57
|
+
Unblock ready task.
|
|
58
|
+
Цель:
|
|
59
|
+
Satisfy depends_on.
|
|
60
|
+
|
|
61
|
+
Свидетельства:
|
|
62
|
+
npm test passed.
|
|
63
|
+
|
|
64
|
+
Метки:
|
|
65
|
+
atom.profile: work_item
|
|
66
|
+
work.id: done-dep
|
|
67
|
+
work.title: Done dependency
|
|
68
|
+
work.status: done
|
|
69
|
+
trace.status: verified
|
|
70
|
+
]>
|
|
71
|
+
|
|
72
|
+
#Задача_ready_eval<[
|
|
73
|
+
Базис:
|
|
74
|
+
Ready task for MCP workflow eval.
|
|
75
|
+
Вектор:
|
|
76
|
+
Claim and inspect via MCP tools.
|
|
77
|
+
Цель:
|
|
78
|
+
Validate LLM-facing read surface.
|
|
79
|
+
Анализ:
|
|
80
|
+
Fixture analysis
|
|
81
|
+
Решение:
|
|
82
|
+
Verdict: useful
|
|
83
|
+
|
|
84
|
+
Метки:
|
|
85
|
+
atom.profile: work_item
|
|
86
|
+
work.id: ready-eval
|
|
87
|
+
work.title: Ready eval task
|
|
88
|
+
work.status: ready
|
|
89
|
+
work.owner_role: engineer
|
|
90
|
+
work.department: agent-platform
|
|
91
|
+
work.priority: high
|
|
92
|
+
work.depends_on: done-dep
|
|
93
|
+
work.target_files: src/workGraphLlmUsefulnessEval.mjs
|
|
94
|
+
work.next_action: run eval harness
|
|
95
|
+
work.decision.verdict: useful
|
|
96
|
+
|
|
97
|
+
критерии_готовности:
|
|
98
|
+
- MCP read surface complete
|
|
99
|
+
- claim workflow succeeds
|
|
100
|
+
]>
|
|
101
|
+
`;
|
|
102
|
+
|
|
103
|
+
function keywordMatch(text, keywords) {
|
|
104
|
+
const haystack = String(text ?? '').toLowerCase();
|
|
105
|
+
return (keywords ?? []).every((keyword) => haystack.includes(String(keyword).toLowerCase()));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function scoreMcpWorkItemReadSurface(item) {
|
|
109
|
+
const missing = MCP_READ_FIELDS_FOR_LLM.filter((field) => !(field in item));
|
|
110
|
+
const emptyCritical = ['id', 'title', 'status'].filter((field) => String(item?.[field] ?? '').trim() === '');
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
ok: missing.length === 0 && emptyCritical.length === 0,
|
|
114
|
+
missing,
|
|
115
|
+
emptyCritical,
|
|
116
|
+
score: Math.max(0, 1 - (missing.length + emptyCritical.length) / MCP_READ_FIELDS_FOR_LLM.length),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export async function evaluateIntentGraphMcpHandlers(handlers, options = {}) {
|
|
121
|
+
if (!handlers?.getIntentHierarchy || !handlers.getArchitectureSnapshot || !handlers.getUnifiedLinkage || !handlers.getPvrgTaskScope) {
|
|
122
|
+
return {
|
|
123
|
+
ok: false,
|
|
124
|
+
skipped: true,
|
|
125
|
+
missingHandlers: MCP_INTENT_GRAPH_TOOLS_V1,
|
|
126
|
+
score: 0,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let seedWorkId = parseWorkItems(SAMPLE_READY_BACKLOG).find((item) => item.status === 'ready')?.id ?? 'ready-eval';
|
|
131
|
+
if (handlers.listWorkItems && options.root) {
|
|
132
|
+
const listed = await handlers.listWorkItems({ limit: 100 }, { root: options.root });
|
|
133
|
+
seedWorkId = listed.find((item) => item.status === 'ready')?.id
|
|
134
|
+
?? listed.find((item) => (item.dependsOn?.length ?? 0) > 0)?.id
|
|
135
|
+
?? listed[0]?.id
|
|
136
|
+
?? seedWorkId;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const checks = [];
|
|
140
|
+
|
|
141
|
+
const hierarchy = await handlers.getIntentHierarchy({}, options);
|
|
142
|
+
checks.push({
|
|
143
|
+
id: 'intent-hierarchy-schema',
|
|
144
|
+
ok: hierarchy?.schema === 'intent.hierarchy.snapshot.v1' && (hierarchy.domains?.length ?? 0) > 0,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const architecture = await handlers.getArchitectureSnapshot({}, options);
|
|
148
|
+
checks.push({
|
|
149
|
+
id: 'architecture-snapshot-schema',
|
|
150
|
+
ok: architecture?.schema === 'architecture.snapshot.v1' && (architecture.blocks?.length ?? 0) > 0,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const linkage = await handlers.getUnifiedLinkage({}, options);
|
|
154
|
+
checks.push({
|
|
155
|
+
id: 'unified-linkage-schema',
|
|
156
|
+
ok: linkage?.schema === 'unified-linkage.projection.v1' && Array.isArray(linkage.links),
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const scope = await handlers.getPvrgTaskScope({ workId: seedWorkId }, options);
|
|
160
|
+
checks.push({
|
|
161
|
+
id: 'pvrg-task-scope-schema',
|
|
162
|
+
ok: scope?.schema === 'pvrg.task-scope.slice.v1' && scope.seedWorkId === seedWorkId,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const passed = checks.filter((check) => check.ok).length;
|
|
166
|
+
return {
|
|
167
|
+
ok: passed === checks.length,
|
|
168
|
+
skipped: false,
|
|
169
|
+
seedWorkId,
|
|
170
|
+
checks,
|
|
171
|
+
score: passed / checks.length,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export async function evaluateCursorMcpContextSurface(handlers, options = {}) {
|
|
176
|
+
const required = [
|
|
177
|
+
'getGraphRagContext',
|
|
178
|
+
'listMemoryRecords',
|
|
179
|
+
'getMemoryRecord',
|
|
180
|
+
'listEvidenceRecords',
|
|
181
|
+
'getEvidenceRecord',
|
|
182
|
+
'readWorkGraphResource',
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
const missingHandlers = required.filter((name) => typeof handlers?.[name] !== 'function');
|
|
186
|
+
if (missingHandlers.length > 0) {
|
|
187
|
+
return {
|
|
188
|
+
ok: false,
|
|
189
|
+
skipped: true,
|
|
190
|
+
missingHandlers,
|
|
191
|
+
score: 0,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let seedWorkId = parseWorkItems(SAMPLE_READY_BACKLOG).find((item) => item.status === 'ready')?.id ?? 'ready-eval';
|
|
196
|
+
if (handlers.listWorkItems && options.root) {
|
|
197
|
+
const listed = await handlers.listWorkItems({ limit: 100 }, { root: options.root });
|
|
198
|
+
seedWorkId = listed.find((item) => item.status === 'ready')?.id
|
|
199
|
+
?? listed.find((item) => item.status === 'done')?.id
|
|
200
|
+
?? listed[0]?.id
|
|
201
|
+
?? seedWorkId;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const checks = [];
|
|
205
|
+
|
|
206
|
+
const graphRag = await handlers.getGraphRagContext({ workId: seedWorkId }, options);
|
|
207
|
+
checks.push({
|
|
208
|
+
id: 'graph-rag-context-schema',
|
|
209
|
+
ok: graphRag?.schema === 'pvrg.graph_rag.context.v1' && graphRag.seedWorkId === seedWorkId,
|
|
210
|
+
});
|
|
211
|
+
checks.push({
|
|
212
|
+
id: 'graph-rag-has-work-nodes',
|
|
213
|
+
ok: (graphRag.currentTaskContext?.workItems?.length ?? 0) >= 1,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const memoryList = await handlers.listMemoryRecords({ workId: seedWorkId, limit: 20 }, options);
|
|
217
|
+
checks.push({
|
|
218
|
+
id: 'memory-record-list-schema',
|
|
219
|
+
ok: memoryList?.schema === 'memory-record-list.v1' && Array.isArray(memoryList.records),
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (memoryList.records.length > 0) {
|
|
223
|
+
const memoryRecord = await handlers.getMemoryRecord({ recordId: memoryList.records[0].id }, options);
|
|
224
|
+
checks.push({
|
|
225
|
+
id: 'memory-record-get-schema',
|
|
226
|
+
ok: memoryRecord?.schema === 'memory-record.v1',
|
|
227
|
+
});
|
|
228
|
+
} else {
|
|
229
|
+
checks.push({
|
|
230
|
+
id: 'memory-record-get-schema',
|
|
231
|
+
ok: true,
|
|
232
|
+
note: 'no memory records in fixture; list schema sufficient',
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const evidenceList = await handlers.listEvidenceRecords({ workId: seedWorkId, limit: 20 }, options);
|
|
237
|
+
checks.push({
|
|
238
|
+
id: 'evidence-record-list-schema',
|
|
239
|
+
ok: evidenceList?.schema === 'evidence-record-list.v1' && Array.isArray(evidenceList.records),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (evidenceList.records.length > 0) {
|
|
243
|
+
const evidenceRecord = await handlers.getEvidenceRecord({ recordId: evidenceList.records[0].id }, options);
|
|
244
|
+
checks.push({
|
|
245
|
+
id: 'evidence-record-get-schema',
|
|
246
|
+
ok: evidenceRecord?.schema === 'evidence-record.v1',
|
|
247
|
+
});
|
|
248
|
+
} else {
|
|
249
|
+
checks.push({
|
|
250
|
+
id: 'evidence-record-get-schema',
|
|
251
|
+
ok: true,
|
|
252
|
+
note: 'no evidence records in fixture; list schema sufficient',
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const graphRagResource = await handlers.readWorkGraphResource(
|
|
257
|
+
`workgraph://pvrg/graph-rag/${encodeURIComponent(seedWorkId)}`,
|
|
258
|
+
options,
|
|
259
|
+
);
|
|
260
|
+
checks.push({
|
|
261
|
+
id: 'graph-rag-resource-schema',
|
|
262
|
+
ok: graphRagResource?.schema === 'pvrg.graph_rag.context.v1',
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const memoryResource = await handlers.readWorkGraphResource('workgraph://memory/records', options);
|
|
266
|
+
checks.push({
|
|
267
|
+
id: 'memory-records-resource-schema',
|
|
268
|
+
ok: memoryResource?.schema === 'memory-record-list.v1',
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
const evidenceResource = await handlers.readWorkGraphResource('workgraph://evidence/records', options);
|
|
272
|
+
checks.push({
|
|
273
|
+
id: 'evidence-records-resource-schema',
|
|
274
|
+
ok: evidenceResource?.schema === 'evidence-record-list.v1',
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const passed = checks.filter((check) => check.ok).length;
|
|
278
|
+
return {
|
|
279
|
+
ok: passed === checks.length,
|
|
280
|
+
skipped: false,
|
|
281
|
+
seedWorkId,
|
|
282
|
+
checks,
|
|
283
|
+
score: passed / checks.length,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function evaluateMcpPromptToolCoverage() {
|
|
288
|
+
const promptText = Object.values(workgraphPrompts)
|
|
289
|
+
.map((prompt) => {
|
|
290
|
+
if (typeof prompt.text === 'function') {
|
|
291
|
+
return prompt.text({});
|
|
292
|
+
}
|
|
293
|
+
return '';
|
|
294
|
+
})
|
|
295
|
+
.join('\n');
|
|
296
|
+
|
|
297
|
+
const rows = MCP_WRITE_TOOLS_V1.map((tool) => ({
|
|
298
|
+
tool,
|
|
299
|
+
mentioned: promptText.includes(tool),
|
|
300
|
+
}));
|
|
301
|
+
|
|
302
|
+
const mentionedCount = rows.filter((row) => row.mentioned).length;
|
|
303
|
+
|
|
304
|
+
return {
|
|
305
|
+
ok: mentionedCount === MCP_WRITE_TOOLS_V1.length,
|
|
306
|
+
mentionedCount,
|
|
307
|
+
total: MCP_WRITE_TOOLS_V1.length,
|
|
308
|
+
rows,
|
|
309
|
+
score: mentionedCount / MCP_WRITE_TOOLS_V1.length,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function evaluateGraphRagUsefulness(items, taskId, options = {}) {
|
|
314
|
+
const budget = options.maxPromptChars ?? DEFAULT_CONTEXT_BUDGET_CHARS;
|
|
315
|
+
const context = buildGraphRagContextForWorkerInput(items, taskId, options.graphRag);
|
|
316
|
+
const promptText = formatGraphRagContextForPrompt(context);
|
|
317
|
+
const slice = context.slice ?? context;
|
|
318
|
+
|
|
319
|
+
const hasTargetFiles = promptText.includes('target') || promptText.includes('workGraphLlmUsefulnessEval');
|
|
320
|
+
const hasDependencies = promptText.includes('depends') || promptText.includes('done-dep');
|
|
321
|
+
const hasEvidenceTrail = promptText.includes('evidence') || (slice.nodes ?? []).some((node) => node.kind === 'evidence');
|
|
322
|
+
const withinBudget = promptText.length <= budget;
|
|
323
|
+
|
|
324
|
+
const signals = [hasTargetFiles, hasDependencies, hasEvidenceTrail, withinBudget];
|
|
325
|
+
const score = signals.filter(Boolean).length / signals.length;
|
|
326
|
+
|
|
327
|
+
return {
|
|
328
|
+
ok: score >= 0.75,
|
|
329
|
+
promptChars: promptText.length,
|
|
330
|
+
nodeCount: slice.nodes?.length ?? 0,
|
|
331
|
+
edgeCount: slice.edges?.length ?? 0,
|
|
332
|
+
hasTargetFiles,
|
|
333
|
+
hasDependencies,
|
|
334
|
+
hasEvidenceTrail,
|
|
335
|
+
withinBudget,
|
|
336
|
+
score,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function evaluateSemanticSearchActionability(searchResult, expectations = {}) {
|
|
341
|
+
const hits = searchResult?.hits ?? [];
|
|
342
|
+
const minHits = expectations.minHits ?? 1;
|
|
343
|
+
const requiredKinds = expectations.requiredKinds ?? ['work_item'];
|
|
344
|
+
const requiredWorkId = expectations.requiredWorkId ?? null;
|
|
345
|
+
|
|
346
|
+
const kindsPresent = new Set(hits.map((hit) => hit.kind));
|
|
347
|
+
const hasRequiredKinds = requiredKinds.every((kind) => kindsPresent.has(kind));
|
|
348
|
+
const hasWorkId = requiredWorkId
|
|
349
|
+
? hits.some((hit) => hit.workId === requiredWorkId)
|
|
350
|
+
: true;
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
ok: hits.length >= minHits && hasRequiredKinds && hasWorkId,
|
|
354
|
+
hitCount: hits.length,
|
|
355
|
+
topScore: hits[0]?.score ?? 0,
|
|
356
|
+
hasRequiredKinds,
|
|
357
|
+
hasWorkId,
|
|
358
|
+
score: hits.length === 0 ? 0 : Math.min(1, hits[0].score / 40),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export async function evaluateMcpTakeNextWorkflow(handlers, options = {}) {
|
|
363
|
+
const root = options.root;
|
|
364
|
+
const handlerOptions = { root };
|
|
365
|
+
|
|
366
|
+
const cycle = await handlers.getCurrentCycle({}, handlerOptions);
|
|
367
|
+
const readyItems = await handlers.listWorkItems({ status: 'ready' }, handlerOptions);
|
|
368
|
+
|
|
369
|
+
const cycleActionable = Array.isArray(cycle.readyQueue) && cycle.readyQueue.length > 0;
|
|
370
|
+
const readyMatchesCycle = cycleActionable
|
|
371
|
+
&& readyItems.some((item) => cycle.readyQueue.includes(item.id));
|
|
372
|
+
|
|
373
|
+
let claimed = null;
|
|
374
|
+
let readSurface = null;
|
|
375
|
+
|
|
376
|
+
if (readyItems.length > 0) {
|
|
377
|
+
const targetId = readyItems[0].id;
|
|
378
|
+
const fullItem = await handlers.getWorkItem({ workId: targetId }, handlerOptions);
|
|
379
|
+
readSurface = scoreMcpWorkItemReadSurface(fullItem);
|
|
380
|
+
|
|
381
|
+
if (options.executeClaim !== false && fullItem.status === 'ready') {
|
|
382
|
+
claimed = await handlers.claimWorkItem({ workId: targetId }, handlerOptions);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const ok = cycleActionable && readyMatchesCycle && readSurface?.ok === true
|
|
387
|
+
&& (options.executeClaim === false || claimed?.newStatus === 'doing');
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
ok,
|
|
391
|
+
cycleActionable,
|
|
392
|
+
readyMatchesCycle,
|
|
393
|
+
readyCount: readyItems.length,
|
|
394
|
+
readSurface,
|
|
395
|
+
claimed,
|
|
396
|
+
score: [
|
|
397
|
+
cycleActionable,
|
|
398
|
+
readyMatchesCycle,
|
|
399
|
+
readSurface?.ok,
|
|
400
|
+
options.executeClaim === false || claimed?.newStatus === 'doing',
|
|
401
|
+
].filter(Boolean).length / 4,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function executeTraceGateWithoutEvidenceFixture() {
|
|
406
|
+
const items = parseWorkItems(`#Задача_gate_task<[
|
|
407
|
+
Базис:
|
|
408
|
+
Gate task.
|
|
409
|
+
Вектор:
|
|
410
|
+
Policy gate.
|
|
411
|
+
Цель:
|
|
412
|
+
Block done without evidence.
|
|
413
|
+
|
|
414
|
+
Метки:
|
|
415
|
+
atom.profile: work_item
|
|
416
|
+
work.id: gate-task
|
|
417
|
+
work.title: Gate task
|
|
418
|
+
work.status: doing
|
|
419
|
+
trace.status: pending
|
|
420
|
+
]>`);
|
|
421
|
+
|
|
422
|
+
try {
|
|
423
|
+
transitionStatus(items[0], 'done');
|
|
424
|
+
return { ok: false, error: 'expected WorkGraphPolicyError' };
|
|
425
|
+
} catch (error) {
|
|
426
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
427
|
+
return {
|
|
428
|
+
ok: message.includes('cannot mark done without evidence'),
|
|
429
|
+
message,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function executePolicyDenialDryRunFixture() {
|
|
435
|
+
const items = parseWorkItems(SAMPLE_READY_BACKLOG);
|
|
436
|
+
const task = items.find((item) => item.id === 'ready-eval');
|
|
437
|
+
const input = buildWorkerInputFromTask(task, {
|
|
438
|
+
policy: { mode: 'execute', allowShell: false, allowNetwork: false, allowFileWrite: false },
|
|
439
|
+
workGraphItems: items,
|
|
440
|
+
});
|
|
441
|
+
const output = runLocalWorker(input);
|
|
442
|
+
const combined = JSON.stringify(output);
|
|
443
|
+
|
|
444
|
+
return {
|
|
445
|
+
ok: output.status === 'failed' && keywordMatch(combined, ['unsupported local runner mode', 'failed']),
|
|
446
|
+
outputStatus: output.status,
|
|
447
|
+
combined,
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function executeWorkerDryRunVerifyProposalFixture() {
|
|
452
|
+
const items = parseWorkItems(SAMPLE_READY_BACKLOG);
|
|
453
|
+
const task = items.find((item) => item.id === 'ready-eval');
|
|
454
|
+
const input = buildWorkerInputFromTask(task, { workGraphItems: items });
|
|
455
|
+
const output = runLocalWorker(input);
|
|
456
|
+
const applied = applyWorkerOutputToItem(task, output);
|
|
457
|
+
const combined = JSON.stringify({ output, applied });
|
|
458
|
+
|
|
459
|
+
return {
|
|
460
|
+
ok: output.status === 'succeeded'
|
|
461
|
+
&& applied.appliedTransition === 'verify'
|
|
462
|
+
&& keywordMatch(combined, ['verify', 'succeeded', 'dry-run']),
|
|
463
|
+
outputStatus: output.status,
|
|
464
|
+
appliedTransition: applied.appliedTransition,
|
|
465
|
+
combined,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export const MANDATORY_PROMPT_EVAL_EXECUTORS = {
|
|
470
|
+
'trace-gate-without-evidence': executeTraceGateWithoutEvidenceFixture,
|
|
471
|
+
'policy-denial-dry-run': executePolicyDenialDryRunFixture,
|
|
472
|
+
'worker-dry-run-verify-proposal': executeWorkerDryRunVerifyProposalFixture,
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
export function runMandatoryPromptEvalFixtures(options = {}) {
|
|
476
|
+
const catalog = buildPromptEvalWorkGraphFixtureCatalog();
|
|
477
|
+
const mandatory = catalog.fixtures.filter((fixture) => fixture.tier === 'mandatory-deterministic');
|
|
478
|
+
const executors = { ...MANDATORY_PROMPT_EVAL_EXECUTORS, ...(options.executors ?? {}) };
|
|
479
|
+
|
|
480
|
+
const results = mandatory.map((fixture) => {
|
|
481
|
+
const executor = executors[fixture.id];
|
|
482
|
+
if (typeof executor !== 'function') {
|
|
483
|
+
return {
|
|
484
|
+
fixtureId: fixture.id,
|
|
485
|
+
ok: false,
|
|
486
|
+
skipped: true,
|
|
487
|
+
reason: 'no_executor',
|
|
488
|
+
tier: fixture.tier,
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const execution = executor(fixture, options);
|
|
493
|
+
const combined = JSON.stringify(execution);
|
|
494
|
+
const keywordsOk = keywordMatch(combined, fixture.expectedKeywords ?? []);
|
|
495
|
+
|
|
496
|
+
return {
|
|
497
|
+
fixtureId: fixture.id,
|
|
498
|
+
ok: Boolean(execution.ok) && (fixture.expectedKeywords?.length ? keywordsOk : true),
|
|
499
|
+
skipped: false,
|
|
500
|
+
tier: fixture.tier,
|
|
501
|
+
failureClass: fixture.failureClass,
|
|
502
|
+
keywordsOk,
|
|
503
|
+
execution,
|
|
504
|
+
};
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
const passed = results.filter((result) => result.ok).length;
|
|
508
|
+
const failed = results.filter((result) => !result.ok && !result.skipped).length;
|
|
509
|
+
const skipped = results.filter((result) => result.skipped).length;
|
|
510
|
+
|
|
511
|
+
return {
|
|
512
|
+
schema: LLM_USEFULNESS_EVAL_SCHEMA,
|
|
513
|
+
kind: 'mandatory-prompt-eval',
|
|
514
|
+
passed,
|
|
515
|
+
failed,
|
|
516
|
+
skipped,
|
|
517
|
+
total: results.length,
|
|
518
|
+
ok: failed === 0 && skipped === 0,
|
|
519
|
+
results: results.sort((left, right) => compareText(left.fixtureId, right.fixtureId)),
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export function buildLlmUsefulnessScorecard(parts) {
|
|
524
|
+
const rawDimensions = [
|
|
525
|
+
{ id: 'mcp-read-surface', weight: 0.2, score: parts.mcpReadSurface?.score ?? 0 },
|
|
526
|
+
{ id: 'mcp-prompt-tool-coverage', weight: 0.15, score: parts.mcpPromptCoverage?.score ?? 0 },
|
|
527
|
+
{ id: 'mcp-workflow', weight: 0.25, score: parts.mcpWorkflow?.score ?? 0, skip: parts.mcpWorkflow?.skipped === true },
|
|
528
|
+
{ id: 'graph-rag-context', weight: 0.2, score: parts.graphRag?.score ?? 0 },
|
|
529
|
+
{
|
|
530
|
+
id: 'mandatory-policy-fixtures',
|
|
531
|
+
weight: 0.2,
|
|
532
|
+
score: parts.mandatoryEval?.ok ? 1 : (parts.mandatoryEval?.passed ?? 0) / Math.max(1, parts.mandatoryEval?.total ?? 1),
|
|
533
|
+
},
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
const dimensions = rawDimensions.filter((dim) => !dim.skip);
|
|
537
|
+
const weightSum = dimensions.reduce((sum, dim) => sum + dim.weight, 0);
|
|
538
|
+
const weighted = dimensions.reduce((sum, dim) => sum + (dim.weight / weightSum) * dim.score, 0);
|
|
539
|
+
|
|
540
|
+
return {
|
|
541
|
+
schema: 'workgraph.llm-usefulness.scorecard.v1',
|
|
542
|
+
overall: Number(weighted.toFixed(3)),
|
|
543
|
+
dimensions: dimensions.map(({ skip, ...dim }) => dim),
|
|
544
|
+
verdict: weighted >= 0.8 ? 'strong' : weighted >= 0.55 ? 'partial' : 'weak',
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
export async function buildWorkGraphLlmUsefulnessReport(options = {}) {
|
|
549
|
+
const mandatoryEval = runMandatoryPromptEvalFixtures(options);
|
|
550
|
+
const mcpPromptCoverage = evaluateMcpPromptToolCoverage();
|
|
551
|
+
|
|
552
|
+
const items = parseWorkItems(SAMPLE_READY_BACKLOG);
|
|
553
|
+
const mcpReadSurface = scoreMcpWorkItemReadSurface(items.find((item) => item.id === 'ready-eval'));
|
|
554
|
+
const graphRag = evaluateGraphRagUsefulness(items, 'ready-eval', options);
|
|
555
|
+
|
|
556
|
+
let mcpWorkflow = { ok: false, score: 0, skipped: true };
|
|
557
|
+
if (options.handlers && options.root) {
|
|
558
|
+
mcpWorkflow = await evaluateMcpTakeNextWorkflow(options.handlers, {
|
|
559
|
+
root: options.root,
|
|
560
|
+
executeClaim: options.executeClaim,
|
|
561
|
+
});
|
|
562
|
+
mcpWorkflow.skipped = false;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
let intentGraphMcp = { ok: false, score: 0, skipped: true };
|
|
566
|
+
if (options.handlers && options.root) {
|
|
567
|
+
intentGraphMcp = await evaluateIntentGraphMcpHandlers(options.handlers, { root: options.root });
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
let cursorMcpContext = { ok: false, score: 0, skipped: true };
|
|
571
|
+
if (options.handlers && options.root) {
|
|
572
|
+
cursorMcpContext = await evaluateCursorMcpContextSurface(options.handlers, { root: options.root });
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
const mcpReadSurfaceBlended = {
|
|
576
|
+
...mcpReadSurface,
|
|
577
|
+
score: intentGraphMcp.skipped && cursorMcpContext.skipped
|
|
578
|
+
? mcpReadSurface.score
|
|
579
|
+
: Number(([
|
|
580
|
+
mcpReadSurface.score,
|
|
581
|
+
...(intentGraphMcp.skipped ? [] : [intentGraphMcp.score]),
|
|
582
|
+
...(cursorMcpContext.skipped ? [] : [cursorMcpContext.score]),
|
|
583
|
+
].reduce((sum, value) => sum + value, 0) / (
|
|
584
|
+
1 + (intentGraphMcp.skipped ? 0 : 1) + (cursorMcpContext.skipped ? 0 : 1)
|
|
585
|
+
)).toFixed(3)),
|
|
586
|
+
intentGraphMcp,
|
|
587
|
+
cursorMcpContext,
|
|
588
|
+
};
|
|
589
|
+
|
|
590
|
+
const scorecard = buildLlmUsefulnessScorecard({
|
|
591
|
+
mcpReadSurface: mcpReadSurfaceBlended,
|
|
592
|
+
mcpPromptCoverage,
|
|
593
|
+
mcpWorkflow,
|
|
594
|
+
graphRag,
|
|
595
|
+
mandatoryEval,
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
return {
|
|
599
|
+
schema: LLM_USEFULNESS_EVAL_SCHEMA,
|
|
600
|
+
scorecard,
|
|
601
|
+
mandatoryEval,
|
|
602
|
+
mcpPromptCoverage,
|
|
603
|
+
mcpReadSurface: mcpReadSurfaceBlended,
|
|
604
|
+
graphRag,
|
|
605
|
+
mcpWorkflow,
|
|
606
|
+
intentGraphMcp,
|
|
607
|
+
cursorMcpContext,
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export { SAMPLE_READY_BACKLOG };
|