@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,168 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { parseStepAtomDrafts } from './stepAtomFormatter.mjs';
|
|
5
|
+
import {
|
|
6
|
+
AGENT_BEHAVIOR_RULES_DIR,
|
|
7
|
+
PORTED_RULE_SOURCE_HINTS,
|
|
8
|
+
WORKER_BEHAVIOR_RULE_IDS,
|
|
9
|
+
loadAgentBehaviorRulesFromDir,
|
|
10
|
+
} from './agentBehaviorRulesBundle.mjs';
|
|
11
|
+
|
|
12
|
+
export const AGENT_BEHAVIOR_RULES_AUDIT_SCHEMA = 'workgraph.agent-behavior-rules-audit.v1';
|
|
13
|
+
|
|
14
|
+
/** Canonical port map vs ../project/rules/agent-behavior/tool-rules-migrated.step */
|
|
15
|
+
export const TOOL_RULES_MIGRATED_PORT_CATALOG = [
|
|
16
|
+
{
|
|
17
|
+
sourceAtom: 'Правила_Заметки_И_Пути',
|
|
18
|
+
status: 'deferred',
|
|
19
|
+
reason: 'Monaco writeFile/readFile/deleteFile tree; Work Graph uses MCP + bounded worker targetFiles',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
sourceAtom: 'Команды_Shell_Npm',
|
|
23
|
+
status: 'deferred',
|
|
24
|
+
reason: 'Sidecar runCommand/bash; worker uses verification matrix gates',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
sourceAtom: 'Режим_Агента_Доп_Правила',
|
|
28
|
+
status: 'adapted',
|
|
29
|
+
workGraphRuleId: 'worker-tool-policy',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
sourceAtom: 'Только_Доставка_Через_Инструмент',
|
|
33
|
+
status: 'deferred',
|
|
34
|
+
reason: 'AGENT_TOOLS / writeFile delivery in Monaco chat',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
sourceAtom: 'Настройка_MCP',
|
|
38
|
+
status: 'deferred',
|
|
39
|
+
reason: 'configureMcpServer UI flow in ioHasC settings',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
sourceAtom: 'Стиль_Исполнения_Composer',
|
|
43
|
+
status: 'deferred',
|
|
44
|
+
reason: 'Composer chat UX; worker returns structured JSON output',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
sourceAtom: 'Режим_По_Умолчанию_Разработчик',
|
|
48
|
+
status: 'ported',
|
|
49
|
+
workGraphRuleId: 'mcp-editing-policy',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
sourceAtom: 'Планирование_И_Инструменты',
|
|
53
|
+
status: 'ported',
|
|
54
|
+
workGraphRuleId: 'mcp-loop-planning',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
sourceAtom: 'Надёжное_Рассуждение_Guardrails',
|
|
58
|
+
status: 'ported',
|
|
59
|
+
workGraphRuleId: 'mcp-read-guardrails',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
sourceAtom: 'После_Правок_LSP',
|
|
63
|
+
status: 'deferred',
|
|
64
|
+
reason: 'Monaco LSP sidecar diagnostics',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
sourceAtom: 'После_Правок_Тесты',
|
|
68
|
+
status: 'adapted',
|
|
69
|
+
workGraphRuleId: 'worker-evidence-gates',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
sourceAtom: 'Формат_Вызовов_Инструментов',
|
|
73
|
+
status: 'deferred',
|
|
74
|
+
reason: 'AGENT_TOOLS markdown / native tool_calls in orchestrator',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
sourceAtom: 'Структурированный_Итог_PVRG',
|
|
78
|
+
status: 'adapted',
|
|
79
|
+
workGraphRuleId: 'mcp-read-guardrails',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
sourceAtom: 'Обратная_Связь_По_Плану',
|
|
83
|
+
status: 'deferred',
|
|
84
|
+
reason: 'Plan mode orchestrator nudges',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
sourceAtom: 'Агент_Low_Code_Устав',
|
|
88
|
+
status: 'deferred',
|
|
89
|
+
reason: 'generateFromCharter sidecar in ioHasC IDE',
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const catalogBySourceAtom = new Map(
|
|
94
|
+
TOOL_RULES_MIGRATED_PORT_CATALOG.map((entry) => [entry.sourceAtom, entry]),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
export async function parseToolRulesMigratedSourceAtomNames(options = {}) {
|
|
98
|
+
const cwd = options.cwd ?? process.cwd();
|
|
99
|
+
const sourcePath = resolve(cwd, options.sourcePath ?? '../project/rules/agent-behavior/tool-rules-migrated.step');
|
|
100
|
+
const text = options.sourceText ?? await readFile(sourcePath, 'utf8');
|
|
101
|
+
return parseStepAtomDrafts(text).map((parsed) => parsed.draft.name);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function auditToolRulesMigratedPort(options = {}) {
|
|
105
|
+
const cwd = options.cwd ?? process.cwd();
|
|
106
|
+
const sourcePath = options.sourcePath ?? '../project/rules/agent-behavior/tool-rules-migrated.step';
|
|
107
|
+
const sourceAtoms = await parseToolRulesMigratedSourceAtomNames({ cwd, sourcePath, sourceText: options.sourceText });
|
|
108
|
+
const allRules = await loadAgentBehaviorRulesFromDir({ cwd, ...options });
|
|
109
|
+
const ruleIds = new Set(allRules.map((rule) => rule.id));
|
|
110
|
+
|
|
111
|
+
const rows = sourceAtoms.map((sourceAtom) => {
|
|
112
|
+
const catalog = catalogBySourceAtom.get(sourceAtom);
|
|
113
|
+
if (!catalog) {
|
|
114
|
+
return {
|
|
115
|
+
sourceAtom,
|
|
116
|
+
status: 'missing_catalog_entry',
|
|
117
|
+
workGraphRuleId: null,
|
|
118
|
+
rulePresent: false,
|
|
119
|
+
ok: false,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const workGraphRuleId = catalog.workGraphRuleId ?? null;
|
|
124
|
+
const rulePresent = workGraphRuleId ? ruleIds.has(workGraphRuleId) : catalog.status === 'deferred';
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
sourceAtom,
|
|
128
|
+
status: catalog.status,
|
|
129
|
+
reason: catalog.reason ?? null,
|
|
130
|
+
workGraphRuleId,
|
|
131
|
+
rulePresent,
|
|
132
|
+
ok: catalog.status === 'deferred' || catalog.status === 'adapted' || rulePresent,
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const covered = rows.filter((row) => row.status === 'ported' || row.status === 'adapted');
|
|
137
|
+
const deferred = rows.filter((row) => row.status === 'deferred');
|
|
138
|
+
const missing = rows.filter((row) => !row.ok);
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
schema: AGENT_BEHAVIOR_RULES_AUDIT_SCHEMA,
|
|
142
|
+
sourcePath,
|
|
143
|
+
rulesDir: AGENT_BEHAVIOR_RULES_DIR,
|
|
144
|
+
workerRuleIds: [...WORKER_BEHAVIOR_RULE_IDS],
|
|
145
|
+
sourceRuleCount: sourceAtoms.length,
|
|
146
|
+
catalogEntryCount: TOOL_RULES_MIGRATED_PORT_CATALOG.length,
|
|
147
|
+
coveredCount: covered.length,
|
|
148
|
+
deferredCount: deferred.length,
|
|
149
|
+
missingCount: missing.length,
|
|
150
|
+
ok: missing.length === 0 && sourceAtoms.length === TOOL_RULES_MIGRATED_PORT_CATALOG.length,
|
|
151
|
+
rows,
|
|
152
|
+
portedSourceHints: PORTED_RULE_SOURCE_HINTS,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function formatAgentBehaviorRulesAuditReport(report) {
|
|
157
|
+
const lines = [
|
|
158
|
+
`agent behavior rules audit: ${report.ok ? 'ok' : 'failed'} (${report.coveredCount} covered/adapted, ${report.deferredCount} deferred, ${report.missingCount} missing)`,
|
|
159
|
+
`source: ${report.sourcePath}`,
|
|
160
|
+
`worker rule ids: ${report.workerRuleIds.join(', ')}`,
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
for (const row of report.rows) {
|
|
164
|
+
lines.push(`${row.ok ? 'ok' : 'fail'}: ${row.sourceAtom} → ${row.status}${row.workGraphRuleId ? ` (${row.workGraphRuleId})` : ''}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return lines.join('\n');
|
|
168
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { collectStepFilePaths } from './promptRulesProjection.mjs';
|
|
5
|
+
import { parseStepAtomDrafts } from './stepAtomFormatter.mjs';
|
|
6
|
+
|
|
7
|
+
export const AGENT_BEHAVIOR_BUNDLE_SCHEMA = 'workgraph.agent-behavior-rules-bundle.v1';
|
|
8
|
+
export const AGENT_BEHAVIOR_RULES_DIR = 'rules/agent-behavior';
|
|
9
|
+
|
|
10
|
+
/** Rule ids injected into worker/OpenAI prompt slice (minimal port subset). */
|
|
11
|
+
export const WORKER_BEHAVIOR_RULE_IDS = [
|
|
12
|
+
'golden-path',
|
|
13
|
+
'worker-tool-policy',
|
|
14
|
+
'worker-provider-neutrality',
|
|
15
|
+
'worker-failure-retry',
|
|
16
|
+
'worker-evidence-gates',
|
|
17
|
+
'worker-task-bound-run',
|
|
18
|
+
'mcp-read-guardrails',
|
|
19
|
+
'mcp-loop-planning',
|
|
20
|
+
'mcp-editing-policy',
|
|
21
|
+
'cursor-ide-workgraph-parity',
|
|
22
|
+
'chat-work-scope-readonly',
|
|
23
|
+
'work-item-create-analysis-decision',
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
/** Rule ids for MCP agent prompt slice (includes worker subset). */
|
|
27
|
+
export const MCP_BEHAVIOR_RULE_IDS = [...WORKER_BEHAVIOR_RULE_IDS];
|
|
28
|
+
|
|
29
|
+
/** Documented port map (subset); full tool-rules-migrated.bvc remains in ../project. */
|
|
30
|
+
export const PORTED_RULE_SOURCE_HINTS = {
|
|
31
|
+
'worker-tool-policy': '../project/rules/agent-behavior/tool-rules-migrated.step (tool policy, bounded scope)',
|
|
32
|
+
'worker-provider-neutrality': '../project/rules/agent-behavior/tool-rules-migrated.step (provider-neutral execution)',
|
|
33
|
+
'worker-failure-retry': '../project/rules/agent-behavior/tool-rules-migrated.step (errors / retry)',
|
|
34
|
+
'worker-evidence-gates': '../project/rules/agent-behavior/tool-rules-migrated.step (evidence / verification)',
|
|
35
|
+
'worker-task-bound-run': '../project/rules/agent-behavior/tool-rules-migrated.step (task-bound agent run)',
|
|
36
|
+
'mcp-read-guardrails': '../project/rules/agent-behavior/tool-rules-migrated.step#Надёжное_Рассуждение_Guardrails',
|
|
37
|
+
'mcp-loop-planning': '../project/rules/agent-behavior/tool-rules-migrated.step#Планирование_И_Инструменты',
|
|
38
|
+
'mcp-editing-policy': '../project/rules/agent-behavior/tool-rules-migrated.step#Режим_По_Умолчанию_Разработчик',
|
|
39
|
+
'cursor-ide-workgraph-parity': 'rules/agent-behavior/cursor-ide-workgraph-parity.bvc',
|
|
40
|
+
'chat-work-scope-readonly': 'rules/agent-behavior/chat-work-scope-readonly.bvc',
|
|
41
|
+
'golden-path': 'rules/agent-behavior/rebuild.bvc',
|
|
42
|
+
'work-item-create-analysis-decision': 'rules/agent-behavior/work-item-create-analysis-decision.bvc',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const DEFAULT_PROMPT_SLICE_MAX_CHARS = 5500;
|
|
46
|
+
|
|
47
|
+
export function buildBehaviorRuleRecord(filePath, draft, labels) {
|
|
48
|
+
const ruleId = labels['rule.id'] ?? draft.name;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
id: ruleId,
|
|
52
|
+
name: draft.name,
|
|
53
|
+
filePath,
|
|
54
|
+
basis: joinLines(draft.basis),
|
|
55
|
+
vector: joinLines(draft.vector),
|
|
56
|
+
goal: joinLines(draft.goal),
|
|
57
|
+
labels,
|
|
58
|
+
bundleGroup: labels['bundle.group'] ?? null,
|
|
59
|
+
traceStatus: labels['trace.status'] ?? 'unknown',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function loadAgentBehaviorRulesFromDir(options = {}) {
|
|
64
|
+
const cwd = options.cwd ?? process.cwd();
|
|
65
|
+
const roots = options.roots ?? [AGENT_BEHAVIOR_RULES_DIR];
|
|
66
|
+
const filePaths = options.filePaths ?? await collectStepFilePaths(cwd, roots);
|
|
67
|
+
const rulesById = new Map();
|
|
68
|
+
|
|
69
|
+
for (const filePath of filePaths) {
|
|
70
|
+
const absolutePath = resolve(cwd, filePath);
|
|
71
|
+
const text = options.fileContents?.[filePath] ?? await readFile(absolutePath, 'utf8');
|
|
72
|
+
|
|
73
|
+
for (const parsed of parseStepAtomDrafts(text)) {
|
|
74
|
+
if (parsed.draft.profile !== 'prompt_rule') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const labels = parsed.draft.labels ?? {};
|
|
79
|
+
const ruleId = labels['rule.id'] ?? parsed.draft.name;
|
|
80
|
+
const record = buildBehaviorRuleRecord(filePath, parsed.draft, labels);
|
|
81
|
+
|
|
82
|
+
if (!parsed.errors.length) {
|
|
83
|
+
rulesById.set(ruleId, record);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return [...rulesById.values()].sort((left, right) => left.id.localeCompare(right.id, 'en'));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function selectWorkerBehaviorRules(allRules, ruleIds = WORKER_BEHAVIOR_RULE_IDS) {
|
|
92
|
+
const byId = new Map(allRules.map((rule) => [rule.id, rule]));
|
|
93
|
+
|
|
94
|
+
return ruleIds
|
|
95
|
+
.map((ruleId) => byId.get(ruleId))
|
|
96
|
+
.filter(Boolean);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function buildAgentBehaviorPromptSlice(rules, options = {}) {
|
|
100
|
+
const maxChars = options.maxChars ?? DEFAULT_PROMPT_SLICE_MAX_CHARS;
|
|
101
|
+
const chunks = [];
|
|
102
|
+
|
|
103
|
+
for (const rule of rules) {
|
|
104
|
+
chunks.push(
|
|
105
|
+
`[${rule.id}]\nБазис: ${rule.basis}\nВектор: ${rule.vector}\nЦель: ${rule.goal}`,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let slice = chunks.join('\n\n');
|
|
110
|
+
|
|
111
|
+
if (slice.length > maxChars) {
|
|
112
|
+
slice = `${slice.slice(0, maxChars - 3)}...`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return slice;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export async function loadAgentBehaviorRulesBundle(options = {}) {
|
|
119
|
+
const cwd = options.cwd ?? process.cwd();
|
|
120
|
+
const ruleIds = options.ruleIds ?? WORKER_BEHAVIOR_RULE_IDS;
|
|
121
|
+
const allRules = await loadAgentBehaviorRulesFromDir({ cwd, ...options });
|
|
122
|
+
const workerRules = selectWorkerBehaviorRules(allRules, ruleIds);
|
|
123
|
+
const missingRuleIds = ruleIds.filter((ruleId) => !workerRules.some((rule) => rule.id === ruleId));
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
schema: AGENT_BEHAVIOR_BUNDLE_SCHEMA,
|
|
127
|
+
rulesDir: AGENT_BEHAVIOR_RULES_DIR,
|
|
128
|
+
ruleIds: workerRules.map((rule) => rule.id),
|
|
129
|
+
workerRules,
|
|
130
|
+
allRules,
|
|
131
|
+
missingRuleIds,
|
|
132
|
+
promptSlice: buildAgentBehaviorPromptSlice(workerRules, options),
|
|
133
|
+
portedSourceHints: PORTED_RULE_SOURCE_HINTS,
|
|
134
|
+
ok: missingRuleIds.length === 0,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function joinLines(values) {
|
|
139
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
140
|
+
return '';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return values.map((value) => String(value).trim()).filter(Boolean).join(' ');
|
|
144
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendWorkerRunJournal,
|
|
3
|
+
readWorkerRunJournal,
|
|
4
|
+
runAgentWorkerLiveLoop,
|
|
5
|
+
} from './agentWorkerLiveLoop.mjs';
|
|
6
|
+
import {
|
|
7
|
+
persistWorkItemUpdateToRepo,
|
|
8
|
+
readWorkItemsFromRepo,
|
|
9
|
+
} from './intentTreeWorkItems.mjs';
|
|
10
|
+
import { buildWorkerProviderCatalog } from './workGraphWorkerProvider.mjs';
|
|
11
|
+
|
|
12
|
+
const AGENT_RUN_RESPONSE_SCHEMA = 'operator.agent-run.response.v1';
|
|
13
|
+
|
|
14
|
+
export function resolveAgentRunProvider(provider) {
|
|
15
|
+
const value = String(provider ?? 'auto').trim().toLowerCase();
|
|
16
|
+
|
|
17
|
+
if (value === '' || value === 'auto') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (value === 'local' || value === 'openai' || value === 'openai-compatible') {
|
|
22
|
+
return value === 'openai-compatible' ? 'openai' : value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
throw new Error(`unsupported agent run provider: ${provider}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function parseAgentRunRequestBody(rawBody) {
|
|
29
|
+
if (rawBody === undefined || rawBody === null) {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (typeof rawBody === 'string' && rawBody.trim() === '') {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const body = typeof rawBody === 'string' ? JSON.parse(rawBody) : rawBody;
|
|
38
|
+
|
|
39
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) {
|
|
40
|
+
throw new TypeError('agent run body must be a JSON object');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return body;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function buildAgentRunResponse(result) {
|
|
47
|
+
return {
|
|
48
|
+
schema: AGENT_RUN_RESPONSE_SCHEMA,
|
|
49
|
+
ok: Boolean(result.ok),
|
|
50
|
+
error: result.error ?? null,
|
|
51
|
+
taskId: result.taskId ?? null,
|
|
52
|
+
steps: Array.isArray(result.steps) ? result.steps : [],
|
|
53
|
+
workerRunSummary: result.workerRunSummary ?? null,
|
|
54
|
+
workerOutput: result.workerOutput ?? null,
|
|
55
|
+
providerResult: result.providerResult ?? null,
|
|
56
|
+
transitionProposal: result.transitionProposal ?? null,
|
|
57
|
+
appliedTransition: result.appliedTransition ?? null,
|
|
58
|
+
transitionError: result.transitionError ?? null,
|
|
59
|
+
persistedBacklog: Boolean(result.persistedBacklog),
|
|
60
|
+
persistBacklogError: result.persistBacklogError ?? null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function executeAgentRun(options = {}) {
|
|
65
|
+
const cwd = options.cwd ?? process.cwd();
|
|
66
|
+
const body = parseAgentRunRequestBody(options.body ?? {});
|
|
67
|
+
const items = await readWorkItemsFromRepo({ ...options, cwd });
|
|
68
|
+
|
|
69
|
+
const provider = resolveAgentRunProvider(body.provider);
|
|
70
|
+
const result = await runAgentWorkerLiveLoop(items, {
|
|
71
|
+
taskId: body.taskId,
|
|
72
|
+
provider,
|
|
73
|
+
enableFallback: body.enableFallback !== false,
|
|
74
|
+
workerInput: body.policyPreset === 'verification'
|
|
75
|
+
? { policy: { mode: 'dry-run' } }
|
|
76
|
+
: { policy: { mode: 'dry-run' } },
|
|
77
|
+
recordedAt: options.recordedAt,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (options.writeJournal !== false && result.workerRunSummary) {
|
|
81
|
+
await appendWorkerRunJournal(result.workerRunSummary, {
|
|
82
|
+
cwd,
|
|
83
|
+
journalPath: options.journalPath,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const persistBacklog = body.persistBacklog !== false && options.persistBacklog !== false;
|
|
88
|
+
let persistedBacklog = false;
|
|
89
|
+
let persistBacklogError = null;
|
|
90
|
+
|
|
91
|
+
if (
|
|
92
|
+
persistBacklog
|
|
93
|
+
&& result.taskId
|
|
94
|
+
&& result.appliedTransition
|
|
95
|
+
&& !result.transitionError
|
|
96
|
+
&& Array.isArray(result.finalItems)
|
|
97
|
+
) {
|
|
98
|
+
const updatedItem = result.finalItems.find((item) => item.id === result.taskId);
|
|
99
|
+
|
|
100
|
+
if (updatedItem) {
|
|
101
|
+
try {
|
|
102
|
+
await persistWorkItemUpdateToRepo({
|
|
103
|
+
...options,
|
|
104
|
+
cwd,
|
|
105
|
+
item: updatedItem,
|
|
106
|
+
});
|
|
107
|
+
persistedBacklog = true;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
persistBacklogError = error instanceof Error ? error.message : String(error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return buildAgentRunResponse({
|
|
115
|
+
...result,
|
|
116
|
+
persistedBacklog,
|
|
117
|
+
persistBacklogError,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function readWorkerProviderCatalogResponse() {
|
|
122
|
+
return buildWorkerProviderCatalog();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export async function readAgentRunJournalResponse(options = {}) {
|
|
126
|
+
const entries = await readWorkerRunJournal({
|
|
127
|
+
cwd: options.cwd,
|
|
128
|
+
journalPath: options.journalPath,
|
|
129
|
+
});
|
|
130
|
+
const limit = Number(options.limit ?? 20);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
schema: 'operator.agent-run.journal.v1',
|
|
134
|
+
entries: entries.slice(-limit).reverse(),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal port of ioHasC agentToolLoopKey loop guard for Work Graph eval/runtime hooks.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const AGENT_TOOL_LOOP_THRESHOLD = 3;
|
|
6
|
+
|
|
7
|
+
function stableJsonFragment(value) {
|
|
8
|
+
if (value === null || value === undefined) {
|
|
9
|
+
return 'null';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const type = typeof value;
|
|
13
|
+
if (type === 'boolean' || type === 'number') {
|
|
14
|
+
return JSON.stringify(value);
|
|
15
|
+
}
|
|
16
|
+
if (type === 'string') {
|
|
17
|
+
return JSON.stringify(value);
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
return `[${value.map((entry) => stableJsonFragment(entry)).join(',')}]`;
|
|
21
|
+
}
|
|
22
|
+
if (type === 'object') {
|
|
23
|
+
const object = /** @type {Record<string, unknown>} */ (value);
|
|
24
|
+
const keys = Object.keys(object).sort();
|
|
25
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJsonFragment(object[key])}`).join(',')}}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return JSON.stringify(String(value));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function agentToolLoopThresholdForTool(toolName, options = {}) {
|
|
32
|
+
const normalized = String(toolName ?? '').trim();
|
|
33
|
+
let base = AGENT_TOOL_LOOP_THRESHOLD;
|
|
34
|
+
|
|
35
|
+
if (normalized === 'claim_work_item' || normalized === 'get_work_item') {
|
|
36
|
+
base = 2;
|
|
37
|
+
} else if (normalized === 'get_pvrg_task_scope' || normalized === 'get_unified_linkage') {
|
|
38
|
+
base = 2;
|
|
39
|
+
} else if (normalized.startsWith('agentWorkGraph')) {
|
|
40
|
+
base = 2;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (
|
|
44
|
+
options.isWeakModel === true
|
|
45
|
+
&& typeof options.maxSameToolCallsWeak === 'number'
|
|
46
|
+
&& options.maxSameToolCallsWeak >= 1
|
|
47
|
+
) {
|
|
48
|
+
return Math.min(base, options.maxSameToolCallsWeak);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return base;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function stableAgentToolLoopKey(toolName, rawArgs) {
|
|
55
|
+
const normalized = String(toolName ?? '').trim();
|
|
56
|
+
const args = rawArgs && typeof rawArgs === 'object' && !Array.isArray(rawArgs)
|
|
57
|
+
? rawArgs
|
|
58
|
+
: {};
|
|
59
|
+
return `${normalized}:${stableJsonFragment(args)}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function formatAgentToolDuplicateInvocationLoopHint(toolName, loopStreak) {
|
|
63
|
+
return `⚠️ LOOP_HINT: инструмент «${toolName}» с теми же аргументами повторён ${loopStreak} раз за этот ход (включая вызовы не подряд). Измени аргументы, выбери другой инструмент или ответь текстом; не зацикливай один и тот же вызов.`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function createAgentToolLoopTracker(options = {}) {
|
|
67
|
+
const counts = new Map();
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
record(toolName, rawArgs) {
|
|
71
|
+
const key = stableAgentToolLoopKey(toolName, rawArgs);
|
|
72
|
+
const nextCount = (counts.get(key) ?? 0) + 1;
|
|
73
|
+
counts.set(key, nextCount);
|
|
74
|
+
const threshold = agentToolLoopThresholdForTool(toolName, options);
|
|
75
|
+
const loopAborted = nextCount >= threshold;
|
|
76
|
+
return {
|
|
77
|
+
key,
|
|
78
|
+
loopStreak: nextCount,
|
|
79
|
+
threshold,
|
|
80
|
+
loopAborted,
|
|
81
|
+
loopHint: loopAborted ? formatAgentToolDuplicateInvocationLoopHint(toolName, nextCount) : null,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
snapshot() {
|
|
85
|
+
return Object.fromEntries(counts.entries());
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|