archgraph-argo 0.11.0 → 0.12.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/argo/defaults/EA-model-template.qea +0 -0
- package/argo/scripts/argo-mcp-server.js +56 -3
- package/argo/scripts/ea-qea-sync-lib.js +688 -0
- package/argo/scripts/ea-qea-sync.js +109 -0
- package/argo/scripts/systemarchitecture-mcp-server.js +73 -0
- package/install-argo.ps1 +23 -89
- package/package.json +3 -5
- package/scripts/ea-layout-store.js +0 -242
- package/scripts/ea-web-service.js +0 -1349
- package/web/app.js +0 -398
- package/web/index.html +0 -86
- package/web/style.css +0 -251
- package/web/vendor/g6.min.js +0 -68
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// WP2791 Node direct .qea projection CLI (no EA, no third-party deps).
|
|
5
|
+
// node argo/scripts/ea-qea-sync.js --graph <json> --qea <file.qea> --mode import|sync|full|export|watch
|
|
6
|
+
// [--delete-confirm-file <f> | -y] [--dry-run] [--snapshot-dir <dir>] [--out <file>] [--no-backup]
|
|
7
|
+
//
|
|
8
|
+
// import/sync : project design/KG graph into the .qea (update-in-place, batch INSERT,
|
|
9
|
+
// full : clear projection-owned content (kg_sync_meta + ArchGraph Sync subtree) then
|
|
10
|
+
// unchanged fingerprint skip, opt-in EA-only delete with confirmation).
|
|
11
|
+
// export : read .qea back into graph-shaped JSON (roundtrip comparable).
|
|
12
|
+
// watch : on graph JSON change, run sync (fs.watch + polling fallback).
|
|
13
|
+
// Every write first snapshots the target as <file>_before_sync_<ts> unless --no-backup.
|
|
14
|
+
|
|
15
|
+
const path = require('node:path');
|
|
16
|
+
const fs = require('node:fs');
|
|
17
|
+
const lib = require(path.join(__dirname, 'ea-qea-sync-lib.js'));
|
|
18
|
+
|
|
19
|
+
function parseArgs(argv) {
|
|
20
|
+
const args = { mode: 'sync', graph: '', qea: '', allowDelete: false, deleteConfirmFile: '', dryRun: false, snapshotDir: '', out: '', noBackup: false, intervalMs: 2000 };
|
|
21
|
+
for (let i = 0; i < argv.length; i++) {
|
|
22
|
+
const a = argv[i];
|
|
23
|
+
const next = () => (i + 1 < argv.length ? argv[++i] : '');
|
|
24
|
+
if (a === '--graph') { args.graph = next(); }
|
|
25
|
+
else if (a === '--qea') { args.qea = next(); }
|
|
26
|
+
else if (a === '--mode') { args.mode = next(); }
|
|
27
|
+
else if (a === '--delete-confirm-file') { args.deleteConfirmFile = next(); args.allowDelete = true; }
|
|
28
|
+
else if (a === '-y' || a === '--yes') { args.allowDelete = true; }
|
|
29
|
+
else if (a === '--dry-run') { args.dryRun = true; }
|
|
30
|
+
else if (a === '--snapshot-dir') { args.snapshotDir = next(); }
|
|
31
|
+
else if (a === '--out') { args.out = next(); }
|
|
32
|
+
else if (a === '--no-backup') { args.noBackup = true; }
|
|
33
|
+
else if (a === '--interval') { args.intervalMs = Number(next()) || 2000; }
|
|
34
|
+
else if (a.startsWith('-')) { /* ignore unknown */ }
|
|
35
|
+
else if (args.modeSet === undefined) { /* positional not used */ }
|
|
36
|
+
}
|
|
37
|
+
return args;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readGraph(jsonPath) {
|
|
41
|
+
const raw = fs.readFileSync(jsonPath, 'utf8').replace(/^\uFEFF/, '');
|
|
42
|
+
return JSON.parse(raw);
|
|
43
|
+
}
|
|
44
|
+
function confirmDelete(args) {
|
|
45
|
+
if (args.allowDelete) { return true; }
|
|
46
|
+
if (args.deleteConfirmFile) {
|
|
47
|
+
try {
|
|
48
|
+
const text = fs.readFileSync(args.deleteConfirmFile, 'utf8').trim().toLowerCase();
|
|
49
|
+
return text.indexOf('delete') >= 0;
|
|
50
|
+
} catch { return false; }
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function main() {
|
|
56
|
+
const args = parseArgs(process.argv.slice(2));
|
|
57
|
+
const cwd = process.cwd();
|
|
58
|
+
const graphPath = path.resolve(cwd, args.graph || 'design/KG/SystemArchitecture.json');
|
|
59
|
+
const qeaPath = path.resolve(cwd, args.qea || 'archgraph.qea');
|
|
60
|
+
if (!fs.existsSync(qeaPath)) {
|
|
61
|
+
console.error('qea not found: ' + qeaPath);
|
|
62
|
+
process.exit(2);
|
|
63
|
+
}
|
|
64
|
+
if (args.mode === 'export') {
|
|
65
|
+
const graph = lib.exportQeaToGraph(qeaPath);
|
|
66
|
+
const text = JSON.stringify(graph, null, 2);
|
|
67
|
+
if (args.out) { fs.writeFileSync(path.resolve(cwd, args.out), text, 'utf8'); console.log('export written to ' + args.out); }
|
|
68
|
+
else { console.log(text); }
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!fs.existsSync(graphPath)) {
|
|
72
|
+
console.error('graph not found: ' + graphPath);
|
|
73
|
+
process.exit(2);
|
|
74
|
+
}
|
|
75
|
+
const graph = readGraph(graphPath);
|
|
76
|
+
if (args.mode === 'watch') {
|
|
77
|
+
// eslint-disable-next-line no-constant-condition
|
|
78
|
+
while (true) {
|
|
79
|
+
runOnce(args, graphPath, qeaPath);
|
|
80
|
+
const m0 = statHash(graphPath);
|
|
81
|
+
await sleep(args.intervalMs);
|
|
82
|
+
const m1 = statHash(graphPath);
|
|
83
|
+
if (m0 !== m1) { continue; } // changed while waiting -> immediate re-sync
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
runOnce(args, graphPath, qeaPath);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function statHash(p) {
|
|
90
|
+
try { const st = fs.statSync(p); return st.size + ':' + st.mtimeMs; } catch { return 'gone'; }
|
|
91
|
+
}
|
|
92
|
+
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
93
|
+
function runOnce(args, graphPath, qeaPath) {
|
|
94
|
+
const graph = readGraph(graphPath);
|
|
95
|
+
let snapshot = null;
|
|
96
|
+
if (!args.dryRun && !args.noBackup) {
|
|
97
|
+
snapshot = lib.snapshotQea(qeaPath, args.snapshotDir || undefined);
|
|
98
|
+
}
|
|
99
|
+
const res = args.mode === 'full'
|
|
100
|
+
? lib.fullProjection(graph, qeaPath, { dryRun: args.dryRun })
|
|
101
|
+
: lib.syncGraphToQea(graph, qeaPath, { dryRun: args.dryRun, allowDelete: confirmDelete(args) });
|
|
102
|
+
const mode = args.dryRun ? 'dry-run' : 'sync';
|
|
103
|
+
console.log(JSON.stringify({ mode, graph: graphPath, qea: qeaPath, snapshot, result: res }, null, 2));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
main().catch((e) => {
|
|
107
|
+
console.error('ea-qea-sync failed: ' + (e && e.message));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('node:fs');
|
|
2
2
|
const path = require('node:path');
|
|
3
|
+
const { spawn } = require('node:child_process');
|
|
3
4
|
const readline = require('node:readline');
|
|
4
5
|
const crypto = require('node:crypto');
|
|
5
6
|
|
|
@@ -1615,6 +1616,25 @@ async function buildMutationResult(context, mutations, write) {
|
|
|
1615
1616
|
writeGraph(context.graphPath.absolutePath, mutationResult.document);
|
|
1616
1617
|
result.written = true;
|
|
1617
1618
|
|
|
1619
|
+
// WP2791: .qea projection parallel to the Neo4j trigger — non-fatal, best-effort.
|
|
1620
|
+
{
|
|
1621
|
+
const qeaTarget = resolveQeaProjectionTarget(context);
|
|
1622
|
+
if (qeaTarget) {
|
|
1623
|
+
try {
|
|
1624
|
+
const projection = await runQeaProjection(qeaTarget);
|
|
1625
|
+
if (projection.ok) {
|
|
1626
|
+
result.qeaProjection = { status: 'passed', qea: qeaTarget.qeaPath, ms: projection.ms };
|
|
1627
|
+
} else {
|
|
1628
|
+
result.qeaProjection = { status: 'failed', qea: qeaTarget.qeaPath, error: projection.error || ('exit ' + projection.code), ms: projection.ms };
|
|
1629
|
+
result.warnings = addUnique(result.warnings || [], ['ea-qea projection failed (non-fatal): ' + (projection.error || ('exit code ' + projection.code))]);
|
|
1630
|
+
}
|
|
1631
|
+
} catch (error) {
|
|
1632
|
+
result.qeaProjection = { status: 'failed', error: String(error && error.message ? error.message : error) };
|
|
1633
|
+
result.warnings = addUnique(result.warnings || [], ['ea-qea projection error (non-fatal): ' + String(error && error.message ? error.message : error)]);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1618
1638
|
if (shouldSyncCanonicalGraphToNeo4j(context.graphPath.relativePath)) {
|
|
1619
1639
|
try {
|
|
1620
1640
|
const syncResult = await syncArchitectureToNeo4j({
|
|
@@ -1812,6 +1832,59 @@ function summarizeDocument(document) {
|
|
|
1812
1832
|
};
|
|
1813
1833
|
}
|
|
1814
1834
|
|
|
1835
|
+
// --- WP2791: post-canonical-write .qea projection (parallel to Neo4j sync, non-fatal) ---
|
|
1836
|
+
// Target resolution (decision qea-full-wholefile-argo-scripts-no-config): env ARGO_EA_QEA >
|
|
1837
|
+
// the single *.qea at the workspace root (0/many -> no-op with an explicit log). NO config file.
|
|
1838
|
+
// Projection script runs from argo/scripts (same package as the MCP runtime), so a workspace
|
|
1839
|
+
// does not need to ship its own projection script (bundled argo/scripts module).
|
|
1840
|
+
function resolveQeaProjectionTarget(context) {
|
|
1841
|
+
try {
|
|
1842
|
+
const workspaceRoot = String(context && context.workspaceRoot ? context.workspaceRoot : '');
|
|
1843
|
+
if (!workspaceRoot || !fs.existsSync(workspaceRoot)) { return null; }
|
|
1844
|
+
const graphAbsolute = context.graphPath && context.graphPath.absolutePath ? context.graphPath.absolutePath : null;
|
|
1845
|
+
if (!graphAbsolute || !fs.existsSync(graphAbsolute)) { return null; }
|
|
1846
|
+
const pick = (p) => (p && fs.existsSync(p) ? path.resolve(p) : null);
|
|
1847
|
+
let qeaPath = pick(process.env.ARGO_EA_QEA);
|
|
1848
|
+
if (qeaPath) { return { qeaPath, graphPath: graphAbsolute, workspaceRoot }; }
|
|
1849
|
+
let qeas = [];
|
|
1850
|
+
try { qeas = fs.readdirSync(workspaceRoot).filter((n) => n.toLowerCase().endsWith('.qea')); } catch { /* ignore */ }
|
|
1851
|
+
if (qeas.length === 1) {
|
|
1852
|
+
return { qeaPath: path.resolve(workspaceRoot, qeas[0]), graphPath: graphAbsolute, workspaceRoot };
|
|
1853
|
+
}
|
|
1854
|
+
console.log('[ea-qea] projection target: none' + (qeas.length > 1 ? ' (' + qeas.length + ' *.qea found; expected exactly one or ARGO_EA_QEA)' : '') + ' in ' + workspaceRoot);
|
|
1855
|
+
return null;
|
|
1856
|
+
} catch (error) {
|
|
1857
|
+
console.log('[ea-qea] projection target resolution failed: ' + String(error && error.message ? error.message : error));
|
|
1858
|
+
return null;
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
function runQeaProjection(target) {
|
|
1863
|
+
return new Promise((resolve) => {
|
|
1864
|
+
const script = path.join(__dirname, 'ea-qea-sync.js');
|
|
1865
|
+
if (!fs.existsSync(script)) {
|
|
1866
|
+
resolve({ ok: false, error: 'argo/scripts/ea-qea-sync.js missing', ms: 0 });
|
|
1867
|
+
return;
|
|
1868
|
+
}
|
|
1869
|
+
const snapshotDir = path.join(target.workspaceRoot, '.argo', 'temp', 'qea-backups');
|
|
1870
|
+
const args = [script, '--mode', 'sync', '--graph', target.graphPath, '--qea', target.qeaPath, '--snapshot-dir', snapshotDir];
|
|
1871
|
+
const started = Date.now();
|
|
1872
|
+
let stderr = '';
|
|
1873
|
+
let child;
|
|
1874
|
+
try {
|
|
1875
|
+
child = spawn(process.execPath, args, { cwd: target.workspaceRoot, windowsHide: true });
|
|
1876
|
+
} catch (error) {
|
|
1877
|
+
resolve({ ok: false, error: String(error && error.message ? error.message : error), ms: Date.now() - started });
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
child.stderr.on('data', (d) => { stderr += String(d); });
|
|
1881
|
+
child.on('error', (err) => resolve({ ok: false, error: String(err && err.message ? err.message : err), ms: Date.now() - started, stderr: stderr.slice(0, 600) }));
|
|
1882
|
+
child.on('close', (code) => {
|
|
1883
|
+
resolve({ ok: code === 0, code, ms: Date.now() - started, stderr: stderr.slice(0, 600) });
|
|
1884
|
+
});
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1815
1888
|
function writeGraph(graphPath, document) {
|
|
1816
1889
|
const tempPath = `${graphPath}.${process.pid}.${Date.now()}.tmp`;
|
|
1817
1890
|
fs.writeFileSync(tempPath, `${JSON.stringify(document, null, 2)}\n`, 'utf8');
|
package/install-argo.ps1
CHANGED
|
@@ -26,10 +26,7 @@ param(
|
|
|
26
26
|
[string]$OpenClawRepoRoot = '',
|
|
27
27
|
[switch]$SkipOpenClaw,
|
|
28
28
|
[string]$McpPath,
|
|
29
|
-
[string]$GraphMcpUrl = 'https://argo.derekworkspacev5.com/mcp'
|
|
30
|
-
[switch]$SkipEaWeb,
|
|
31
|
-
[int]$EaWebPort = 8787,
|
|
32
|
-
[string]$EaWebRoot = ''
|
|
29
|
+
[string]$GraphMcpUrl = 'https://argo.derekworkspacev5.com/mcp'
|
|
33
30
|
)
|
|
34
31
|
|
|
35
32
|
$ErrorActionPreference = 'Stop'
|
|
@@ -740,37 +737,37 @@ Write-Host '==> Deploying Argo toolchain'
|
|
|
740
737
|
|
|
741
738
|
$schemaSrc = Join-Path $argoDir 'schema'
|
|
742
739
|
$schemaDest = Join-Path $ArgoRoot 'schema'
|
|
743
|
-
Write-Host "[1/
|
|
740
|
+
Write-Host "[1/22] argo\schema -> $schemaDest"
|
|
744
741
|
Copy-Tree -Source $schemaSrc -Destination $schemaDest
|
|
745
742
|
|
|
746
743
|
$scriptsSrc = Join-Path $argoDir 'scripts'
|
|
747
744
|
$scriptsDest = Join-Path $ArgoRoot 'scripts'
|
|
748
|
-
Write-Host "[2/
|
|
745
|
+
Write-Host "[2/22] argo\scripts -> $scriptsDest"
|
|
749
746
|
Copy-Tree -Source $scriptsSrc -Destination $scriptsDest
|
|
750
747
|
|
|
751
748
|
$defaultsSrc = Join-Path $argoDir 'defaults'
|
|
752
749
|
$defaultsDest = Join-Path $ArgoRoot 'defaults'
|
|
753
|
-
Write-Host "[3/
|
|
750
|
+
Write-Host "[3/22] argo\defaults -> $defaultsDest"
|
|
754
751
|
Copy-Tree -Source $defaultsSrc -Destination $defaultsDest
|
|
755
752
|
|
|
756
753
|
$skillSrc = Join-Path (Join-Path $argoDir 'skills') 'argo-init'
|
|
757
754
|
$skillDest = Join-Path $SkillsRoot 'argo-init'
|
|
758
|
-
Write-Host "[4/
|
|
755
|
+
Write-Host "[4/22] argo\skills\argo-init -> $skillDest"
|
|
759
756
|
Copy-Tree -Source $skillSrc -Destination $skillDest
|
|
760
757
|
|
|
761
758
|
$ruleSrc = Join-Path (Join-Path $argoDir 'rules') 'archgraph.instructions.md'
|
|
762
759
|
$ruleDest = Join-Path $PromptsRoot 'archgraph.instructions.md'
|
|
763
|
-
Write-Host "[5/
|
|
760
|
+
Write-Host "[5/22] argo\rules\archgraph.instructions.md -> $ruleDest"
|
|
764
761
|
New-Item -ItemType Directory -Force -Path $PromptsRoot | Out-Null
|
|
765
762
|
Copy-Item -Force -Path $ruleSrc -Destination $ruleDest
|
|
766
763
|
|
|
767
764
|
$depsSrc = Join-Path $argoDir 'package.json'
|
|
768
765
|
$depsDest = Join-Path $ArgoRoot 'package.json'
|
|
769
|
-
Write-Host "[6/
|
|
766
|
+
Write-Host "[6/22] argo\package.json -> $depsDest"
|
|
770
767
|
Copy-Item -Force -Path $depsSrc -Destination $depsDest
|
|
771
768
|
|
|
772
769
|
$cursorSkillDest = Join-Path $CursorSkillsRoot 'argo-init'
|
|
773
|
-
Write-Host "[7/
|
|
770
|
+
Write-Host "[7/22] argo\skills\argo-init -> $cursorSkillDest (Cursor)"
|
|
774
771
|
Copy-Tree -Source $skillSrc -Destination $cursorSkillDest
|
|
775
772
|
|
|
776
773
|
$mcpBridgeSrc = Join-Path $argoDir 'mcp-bridges'
|
|
@@ -779,29 +776,29 @@ Write-Host " argo\mcp-bridges -> $mcpBridgeDest (Cursor graph-mcp stdio bridge)
|
|
|
779
776
|
Copy-Tree -Source $mcpBridgeSrc -Destination $mcpBridgeDest
|
|
780
777
|
|
|
781
778
|
$openCodeSkillDest = Join-Path $OpenCodeSkillsRoot 'argo-init'
|
|
782
|
-
Write-Host "[8/
|
|
779
|
+
Write-Host "[8/22] argo\skills\argo-init -> $openCodeSkillDest (OpenCode)"
|
|
783
780
|
Copy-Tree -Source $skillSrc -Destination $openCodeSkillDest
|
|
784
781
|
|
|
785
|
-
Write-Host "[9/
|
|
782
|
+
Write-Host "[9/22] argo\rules\archgraph.instructions.md -> $OpenCodeAgentsPath (OpenCode global AGENTS.md)"
|
|
786
783
|
Add-AgentsRule -AgentsPath $OpenCodeAgentsPath -RulePath $ruleSrc
|
|
787
784
|
|
|
788
785
|
$agentsSrc = Join-Path $argoDir 'agents'
|
|
789
|
-
Write-Host "[10/
|
|
786
|
+
Write-Host "[10/22] argo\agents -> $CopilotAgentsRoot (Copilot user-level)"
|
|
790
787
|
Copy-Agents -Source $agentsSrc -Destination $CopilotAgentsRoot
|
|
791
788
|
|
|
792
|
-
Write-Host "[11/
|
|
789
|
+
Write-Host "[11/22] argo\agents -> $CursorAgentsRoot (Cursor user-level, converted to .md)"
|
|
793
790
|
Copy-Agents -Source $agentsSrc -Destination $CursorAgentsRoot -Target cursor
|
|
794
791
|
|
|
795
|
-
Write-Host "[12/
|
|
792
|
+
Write-Host "[12/22] argo\agents -> $OpenCodeAgentsRoot (OpenCode user-level, converted to .md)"
|
|
796
793
|
Copy-Agents -Source $agentsSrc -Destination $OpenCodeAgentsRoot -Target opencode
|
|
797
794
|
|
|
798
795
|
$pluginsSrc = Join-Path $argoDir 'plugins'
|
|
799
|
-
Write-Host "[13/
|
|
796
|
+
Write-Host "[13/22] argo\plugins -> $PluginsRoot (Argo opencode plugins)"
|
|
800
797
|
Copy-Tree -Source $pluginsSrc -Destination $PluginsRoot
|
|
801
798
|
|
|
802
799
|
$cursorRuleSrc = Join-Path (Join-Path $argoDir 'rules') 'archgraph.instructions.md'
|
|
803
800
|
$cursorRuleDest = Join-Path $CursorRulesRoot 'archgraph.mdc'
|
|
804
|
-
Write-Host "[14/
|
|
801
|
+
Write-Host "[14/22] argo\rules\archgraph.instructions.md -> $cursorRuleDest (Cursor global rule, alwaysApply)"
|
|
805
802
|
New-Item -ItemType Directory -Force -Path $CursorRulesRoot | Out-Null
|
|
806
803
|
Convert-RuleFile -SourceFile $cursorRuleSrc -DestinationFile $cursorRuleDest
|
|
807
804
|
|
|
@@ -813,16 +810,16 @@ if ($SkipDsh) {
|
|
|
813
810
|
$patchPath = Join-Path $DshHome 'cordis.patch.yml'
|
|
814
811
|
$argoServer = (Join-Path $ArgoRoot 'scripts\argo-mcp-server.js').Replace('\', '/')
|
|
815
812
|
|
|
816
|
-
Write-Host "[15/
|
|
813
|
+
Write-Host "[15/22] argo\rules\archgraph.instructions.md -> $DshHome\AGENTS.md (DeepSeek Harness user-global rule, frontmatter stripped)"
|
|
817
814
|
Write-DshAgentRule -DshHome $DshHome -RuleText $ruleSrcContent
|
|
818
815
|
|
|
819
|
-
Write-Host "[16/
|
|
816
|
+
Write-Host "[16/22] argo\skills\argo-init -> $dshSkillDest (DeepSeek Harness skill)"
|
|
820
817
|
Copy-Tree -Source (Join-Path $argoDir 'skills\argo-init') -Destination $dshSkillDest
|
|
821
818
|
|
|
822
|
-
Write-Host "[17/
|
|
819
|
+
Write-Host "[17/22] argo\rules\<WakeupGuideline> -> $DshHome\plugins\dsh-argo-wakeup\index.js (DeepSeek Harness wakeup plugin)"
|
|
823
820
|
$wakeupDshPath = New-DshWakeupPlugin -DshHome $DshHome -RuleText $ruleSrcContent
|
|
824
821
|
|
|
825
|
-
Write-Host "[18/
|
|
822
|
+
Write-Host "[18/22] argo-workspace + argo-wakeup rows -> $patchPath (DeepSeek Harness MCP bridge + wakeup plugin)"
|
|
826
823
|
# The generated dsh-argo-workspace bridge connects directly to the argo
|
|
827
824
|
# server (no dsh-mcp-client row), registers every tool as mcp__argo__* and
|
|
828
825
|
# injects the current session's workspace (SessionHeader.cwd) as the
|
|
@@ -853,7 +850,7 @@ if ($SkipDsh) {
|
|
|
853
850
|
Write-DshManagedBlock -Path $patchPath -Block $block -MarkerStart '# BEGIN ArchGraph ARGO deployment' -MarkerEnd '# END ArchGraph ARGO deployment'
|
|
854
851
|
}
|
|
855
852
|
|
|
856
|
-
Write-Host "[19/
|
|
853
|
+
Write-Host "[19/22] argo\agents -> $DshHome\.agent-presets\<id> (DeepSeek Harness agent presets)"
|
|
857
854
|
New-DshAgentPresets -DshHome $DshHome -AgentsSrc (Join-Path $argoDir 'agents')
|
|
858
855
|
|
|
859
856
|
Write-Host " note: graph-mcp remote ($GraphMcpUrl) is NOT registered for DeepSeek Harness -"
|
|
@@ -874,10 +871,10 @@ if ($SkipOpenClaw) {
|
|
|
874
871
|
$openClawAgentsDest = Join-Path $OpenClawWorkspace 'AGENTS.md'
|
|
875
872
|
|
|
876
873
|
Write-Host '==> Deploying OpenClaw integration'
|
|
877
|
-
Write-Host "[20/
|
|
874
|
+
Write-Host "[20/22] argo\rules\archgraph.instructions.md -> $openClawAgentsDest (OpenClaw workspace AGENTS.md, frontmatter stripped)"
|
|
878
875
|
Write-OpenClawAgentRule -OpenClawWorkspace $OpenClawWorkspace -RuleText $ruleSrcContent
|
|
879
876
|
|
|
880
|
-
Write-Host "[21/
|
|
877
|
+
Write-Host "[21/22] argo\skills\argo-init -> $openClawSkillDest (OpenClaw managed skill, all agents)"
|
|
881
878
|
Copy-Tree -Source (Join-Path $argoDir 'skills\argo-init') -Destination $openClawSkillDest
|
|
882
879
|
|
|
883
880
|
Write-Host ' OpenClaw injects AGENTS.md into Project Context on every session, so the wakeup'
|
|
@@ -1046,7 +1043,7 @@ if ($SkipMcp) {
|
|
|
1046
1043
|
# location; -OpenClawRepoRoot overrides it (e.g. for tests or when the
|
|
1047
1044
|
# installer runs from a non-workspace npm-global package dir).
|
|
1048
1045
|
$openClawRepoRoot = if ($OpenClawRepoRoot) { $OpenClawRepoRoot } else { $repoRoot }
|
|
1049
|
-
Write-Host "[22/
|
|
1046
|
+
Write-Host "[22/22] argo MCP server -> $(Join-Path $OpenClawHome 'openclaw.json') (OpenClaw mcp.servers.argo, env.ARGO_REPO_ROOT pinned)"
|
|
1050
1047
|
Write-OpenClawMcpConfig -OpenClawHome $OpenClawHome -RepoRoot $openClawRepoRoot -ArgoServer $argoServer -GraphMcpServer $openClawGraphMcpServer
|
|
1051
1048
|
}
|
|
1052
1049
|
}
|
|
@@ -1058,68 +1055,5 @@ if (Test-Path $wakeupPluginPath) {
|
|
|
1058
1055
|
Write-Host "argo-wakeup plugin registered -> $OpenCodeConfigPath"
|
|
1059
1056
|
}
|
|
1060
1057
|
|
|
1061
|
-
# EA local web service (WP2786): deploy the two service scripts next to the
|
|
1062
|
-
# harness scripts (REPO_ROOT = $ArgoRoot keeps the relative layout intact) plus
|
|
1063
|
-
# the web/ statics, then start the service in the background. Re-running the
|
|
1064
|
-
# installer is idempotent: an occupied port skips the startup.
|
|
1065
|
-
$eaServiceSrc = Join-Path $repoRoot 'scripts\ea-web-service.js'
|
|
1066
|
-
$eaLayoutStoreSrc = Join-Path $repoRoot 'scripts\ea-layout-store.js'
|
|
1067
|
-
$eaWebSrc = Join-Path $repoRoot 'web'
|
|
1068
|
-
Write-Host "[23/23] scripts\ea-web-service.js + scripts\ea-layout-store.js + web -> $ArgoRoot (EA local web service)"
|
|
1069
|
-
if ((Test-Path $eaServiceSrc) -and (Test-Path $eaLayoutStoreSrc) -and (Test-Path $eaWebSrc)) {
|
|
1070
|
-
Copy-Item -Force -Path $eaServiceSrc -Destination (Join-Path $scriptsDest 'ea-web-service.js')
|
|
1071
|
-
Copy-Item -Force -Path $eaLayoutStoreSrc -Destination (Join-Path $scriptsDest 'ea-layout-store.js')
|
|
1072
|
-
Copy-Tree -Source $eaWebSrc -Destination (Join-Path $ArgoRoot 'web')
|
|
1073
|
-
Write-Host " service scripts + web statics deployed -> $scriptsDest / $(Join-Path $ArgoRoot 'web')"
|
|
1074
|
-
if ($SkipEaWeb) {
|
|
1075
|
-
Write-Host ' EA web service startup skipped (-SkipEaWeb)'
|
|
1076
|
-
}
|
|
1077
|
-
else {
|
|
1078
|
-
$eaWebRoot = if ($EaWebRoot) { $EaWebRoot } else { $PWD.Path }
|
|
1079
|
-
$eaPortInUse = $false
|
|
1080
|
-
try {
|
|
1081
|
-
$eaProbe = New-Object System.Net.Sockets.TcpClient
|
|
1082
|
-
$eaProbe.Connect('127.0.0.1', $EaWebPort)
|
|
1083
|
-
$eaPortInUse = $true
|
|
1084
|
-
$eaProbe.Close()
|
|
1085
|
-
}
|
|
1086
|
-
catch {
|
|
1087
|
-
$eaPortInUse = $false
|
|
1088
|
-
}
|
|
1089
|
-
if ($eaPortInUse) {
|
|
1090
|
-
Write-Host " EA web service already listening on 127.0.0.1:$EaWebPort; startup skipped (idempotent re-deploy)"
|
|
1091
|
-
}
|
|
1092
|
-
else {
|
|
1093
|
-
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
|
|
1094
|
-
if (-not $nodeCmd) {
|
|
1095
|
-
throw 'EA web service startup failed: node not found on PATH'
|
|
1096
|
-
}
|
|
1097
|
-
$eaServiceDest = Join-Path $scriptsDest 'ea-web-service.js'
|
|
1098
|
-
$eaLogOut = Join-Path $ArgoRoot 'ea-web-service.log'
|
|
1099
|
-
$eaLogErr = Join-Path $ArgoRoot 'ea-web-service.err.log'
|
|
1100
|
-
# Start the service through WMI (Win32_Process.Create) instead of
|
|
1101
|
-
# Start-Process: the process is then created by the WMI service and
|
|
1102
|
-
# inherits NONE of this installer's stdio pipe handles. Inherited
|
|
1103
|
-
# pipes would keep spawnSync-based launchers (argo-deploy bin, tests)
|
|
1104
|
-
# blocked until the service exits. cmd.exe is used only to redirect
|
|
1105
|
-
# the service stdout/stderr into log files.
|
|
1106
|
-
$q = [char]34
|
|
1107
|
-
$eaCmdLine = "cmd.exe /S /c $q$q$($nodeCmd.Source)$q $q$eaServiceDest$q --root $q$eaWebRoot$q --port $EaWebPort > $q$eaLogOut$q 2> $q$eaLogErr$q$q"
|
|
1108
|
-
$eaCreate = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{
|
|
1109
|
-
CommandLine = $eaCmdLine
|
|
1110
|
-
CurrentDirectory = $ArgoRoot
|
|
1111
|
-
}
|
|
1112
|
-
if ($eaCreate.ReturnValue -ne 0) {
|
|
1113
|
-
throw "EA web service startup failed: Win32_Process.Create ReturnValue $($eaCreate.ReturnValue)"
|
|
1114
|
-
}
|
|
1115
|
-
Write-Host " EA web service started in background (pid $($eaCreate.ProcessId)): http://127.0.0.1:$EaWebPort (root: $eaWebRoot)"
|
|
1116
|
-
Write-Host " logs: $eaLogOut / $eaLogErr"
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
else {
|
|
1121
|
-
Write-Host ' EA web service sources not present in this package; step skipped'
|
|
1122
|
-
}
|
|
1123
|
-
|
|
1124
1058
|
Write-Host ''
|
|
1125
1059
|
Write-Host 'Argo deployment complete.'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "archgraph-argo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Deploy the ArchGraph ARGO toolchain, skills, and rules (schema, scripts, argo-init skill, global rule) with one command.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -16,9 +16,6 @@
|
|
|
16
16
|
"argo/skills/argo-init",
|
|
17
17
|
"argo/rules",
|
|
18
18
|
"argo/package.json",
|
|
19
|
-
"scripts/ea-web-service.js",
|
|
20
|
-
"scripts/ea-layout-store.js",
|
|
21
|
-
"web",
|
|
22
19
|
"vendor",
|
|
23
20
|
"install-argo.ps1",
|
|
24
21
|
"bin",
|
|
@@ -41,7 +38,8 @@
|
|
|
41
38
|
"neo4j-driver": "^6.2.0"
|
|
42
39
|
},
|
|
43
40
|
"devDependencies": {
|
|
44
|
-
"@resvg/resvg-js": "^2.6.2"
|
|
41
|
+
"@resvg/resvg-js": "^2.6.2",
|
|
42
|
+
"playwright": "1.61.1"
|
|
45
43
|
},
|
|
46
44
|
"scripts": {
|
|
47
45
|
"test": "node --test \"tests/*.test.js\""
|