archgraph-argo 0.26.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/install-argo.ps1 CHANGED
@@ -25,6 +25,9 @@ param(
25
25
  [string]$OpenClawWorkspace = "$env:USERPROFILE\.openclaw\workspace",
26
26
  [string]$OpenClawRepoRoot = '',
27
27
  [switch]$SkipOpenClaw,
28
+ [string]$DoubaoHome = "$env:USERPROFILE\Doubao",
29
+ [string]$DoubaoWorkspace = "$env:LOCALAPPDATA\Doubao\User Data\Default\.doubao\agent_mode\workspace",
30
+ [switch]$SkipDoubao,
28
31
  [string]$McpPath,
29
32
  [string]$GraphMcpUrl = 'https://argo.derekworkspacev5.com/mcp'
30
33
  )
@@ -298,16 +301,6 @@ function Get-MarkdownBody {
298
301
  return $m.Groups[2].Value
299
302
  }
300
303
 
301
- function Get-WakeupGuideline {
302
- # Extract the <WakeupGuideline>...</WakeupGuideline> block from the rule
303
- # text, so the DSH wakeup plugin is generated from the same source the
304
- # Copilot / Cursor / OpenCode rules use.
305
- param([string]$RuleText)
306
- $m = [regex]::Match($RuleText, '(?s)<WakeupGuideline>(.*?)</WakeupGuideline>')
307
- if (-not $m.Success) { return '' }
308
- return $m.Groups[1].Value.Trim()
309
- }
310
-
311
304
  function Write-ArchGraphRuleBlock {
312
305
  # Merge the frontmatter-stripped ArchGraph rule into a target AGENTS.md
313
306
  # file (DSH home or OpenClaw workspace), replacing the previous ArchGraph
@@ -372,6 +365,149 @@ function Write-OpenClawAgentRule {
372
365
  Write-ArchGraphRuleBlock -DestPath (Join-Path $OpenClawWorkspace 'AGENTS.md') -RuleText $RuleText -Label 'OpenClaw rule'
373
366
  }
374
367
 
368
+ function Convert-SkillFile {
369
+ # Normalize an ArchGraph SKILL.md for the Doubao (desktop agent mode) skill
370
+ # system. Doubao follows the Anthropic Agent Skills spec: the YAML
371
+ # frontmatter may contain ONLY `name` and `description` (see the built-in
372
+ # skill-creator-for-work skill); any other field is rejected. The ArchGraph
373
+ # skills additionally carry VS Code / OpenCode-only fields (argument-hint,
374
+ # disable-model-invocation), so strip the frontmatter down to name +
375
+ # description while keeping the body verbatim and the values byte-intact.
376
+ param(
377
+ [string]$SourceFile,
378
+ [string]$DestinationFile
379
+ )
380
+ $content = Get-Content $SourceFile -Raw -Encoding UTF8
381
+ $m = [regex]::Match($content, '(?s)^---\s*\r?\n(.*?)\r?\n---\s*\r?\n(.*)$')
382
+ if (-not $m.Success) {
383
+ Copy-Item -Force -Path $SourceFile -Destination $DestinationFile
384
+ return
385
+ }
386
+ $front = $m.Groups[1].Value
387
+ $body = $m.Groups[2].Value
388
+
389
+ $name = ''
390
+ $desc = ''
391
+ $nm = [regex]::Match($front, '(?m)^name:\s*(.*)$')
392
+ if ($nm.Success) { $name = $nm.Groups[1].Value.Trim().Trim('"').Trim("'") }
393
+ # Keep the description value verbatim (including any surrounding quotes) so
394
+ # non-ASCII and internal punctuation survive the round-trip byte-for-byte.
395
+ $dm = [regex]::Match($front, '(?m)^description:\s*(.*)$')
396
+ if ($dm.Success) { $desc = $dm.Groups[1].Value.Trim() }
397
+
398
+ $newFront = "---`r`n"
399
+ if ($name) { $newFront += "name: $name`r`n" }
400
+ if ($desc) { $newFront += "description: $desc`r`n" }
401
+ $newFront += "---`r`n"
402
+
403
+ $result = $newFront + "`r`n" + $body
404
+ [System.IO.File]::WriteAllText($DestinationFile, $result, (New-Object System.Text.UTF8Encoding $false))
405
+ }
406
+
407
+ function Copy-DoubaoSkills {
408
+ # Deploy the ArchGraph skills into a Doubao skill root. Doubao adopts the
409
+ # Anthropic Agent Skills layout: one folder per skill containing SKILL.md
410
+ # (plus optional scripts/references/assets). The metadata (name +
411
+ # description) is always in context; the body loads only when the skill
412
+ # triggers. SKILL.md is normalized via Convert-SkillFile; any bundled
413
+ # resources are copied verbatim so the skill folder is self-contained.
414
+ param(
415
+ [string]$Root,
416
+ [string]$SourceSkillsRoot,
417
+ [string[]]$SkillNames,
418
+ [string]$Label
419
+ )
420
+ foreach ($skill in $SkillNames) {
421
+ $src = Join-Path $SourceSkillsRoot $skill
422
+ if (-not (Test-Path (Join-Path $src 'SKILL.md'))) { continue }
423
+ $destDir = Join-Path $Root $skill
424
+ New-Item -ItemType Directory -Force -Path $destDir | Out-Null
425
+ Copy-Item -Recurse -Force -Path (Join-Path $src '*') -Destination $destDir
426
+ Convert-SkillFile -SourceFile (Join-Path $src 'SKILL.md') -DestinationFile (Join-Path $destDir 'SKILL.md')
427
+ }
428
+ Write-Host " argo skills -> $Root ($Label)"
429
+ }
430
+
431
+ function Convert-RuleToSkill {
432
+ # Package the single-source ARGO rule file (argo/rules/archgraph.instructions.md)
433
+ # as a Doubao entry skill. Doubao keeps ONLY a skill's name + description in
434
+ # context permanently (the body loads when the skill triggers) and it
435
+ # forbids angle brackets in the description. So the frontmatter carries a
436
+ # mandatory trigger description (the STEP 0 gate + the "load before any
437
+ # intent-graph read/write" mandate) and the body is the rule text verbatim
438
+ # (frontmatter stripped). This is the closest Doubao allows to an always-on
439
+ # rule: Doubao has no system-prompt / AGENTS.md hook.
440
+ param(
441
+ [string]$RuleFile,
442
+ [string]$DestinationFile
443
+ )
444
+ $rule = Get-Content $RuleFile -Raw -Encoding UTF8
445
+ $body = Get-MarkdownBody -Content $rule
446
+ $description = 'MANDATORY entry skill for the ARGO / ArchGraph intent graph. Whenever the workspace is an ArchGraph workspace (contains design/KG/SystemArchitecture.json) or the argo MCP tools (mcp__argo__*) are available, you MUST load this skill BEFORE reading, querying or writing the architecture graph. STEP 0 gate: identify your Business Actor through the argo MCP and restore your working memory first, then follow this skill for KG-first retrieval, the ARGO red lines, acceptance-test-first work, deduplicated and lossless graph writes, and commit tracing.'
447
+ $front = "---`r`nname: archgraph-argo`r`ndescription: `"$description`"`r`n---`r`n"
448
+ [System.IO.File]::WriteAllText($DestinationFile, ($front + "`r`n" + $body), (New-Object System.Text.UTF8Encoding $false))
449
+ }
450
+
451
+ function Write-DoubaoMcpRecipe {
452
+ # Doubao's desktop agent mode registers MCP servers through its in-app UI
453
+ # (自定义连接器: 传输类型 STDIO / 命令 / 参数 / 环境变量), NOT through a config
454
+ # file, so the installer cannot auto-register. This writes the exact
455
+ # connector values to a reference file and prints a copy-paste recipe.
456
+ #
457
+ # The argo server is a local stdio child with NO fixed workspace: Doubao's
458
+ # MCP client (rmcp) supports the MCP `roots` handshake and passes a
459
+ # `workingDirectory` when spawning a stdio connector, so argo follows the
460
+ # workspace the user selected in Doubao - exactly like the OpenCode (roots)
461
+ # and DeepSeek Harness (injected workspaceRoot) hosts. ARGO_REPO_ROOT is
462
+ # therefore NOT pinned; it remains available as an optional override.
463
+ # graph-mcp (remote Streamable HTTP) is exposed through the same stdio
464
+ # bridge the Cursor deployment uses.
465
+ param(
466
+ [string]$RecipePath,
467
+ [string]$ArgoServer,
468
+ [string]$BridgePath,
469
+ [string]$GraphMcpUrl
470
+ )
471
+ $argoServerSlash = ($ArgoServer -replace '\\', '/')
472
+ $connectors = @(
473
+ [ordered]@{
474
+ serverName = 'argo'
475
+ transport = 'STDIO'
476
+ command = 'node'
477
+ args = @($argoServerSlash)
478
+ }
479
+ )
480
+ if ($BridgePath) {
481
+ $connectors += [ordered]@{
482
+ serverName = 'graph-mcp'
483
+ transport = 'STDIO'
484
+ command = 'node'
485
+ args = @(($BridgePath -replace '\\', '/'))
486
+ env = [ordered]@{ GRAPH_MCP_URL = $GraphMcpUrl }
487
+ }
488
+ }
489
+ $recipe = [ordered]@{
490
+ host = 'Doubao desktop (agent mode) - custom connector (自定义连接器), manual in-app registration'
491
+ note = 'Open Doubao agent mode -> MCP/connector settings -> add a custom connector -> enter the values below (transport 传输类型 = STDIO). Requires Node.js on PATH. Doubao custom connectors run only on the local machine.'
492
+ workspace = 'The argo connector has no fixed workspace: it follows the workspace selected in Doubao (MCP roots / connector workingDirectory), the same way OpenCode (roots) and DeepSeek Harness (injected workspaceRoot) do. To pin a fixed workspace instead, add env ARGO_REPO_ROOT=<absolute project path>.'
493
+ connectors = $connectors
494
+ }
495
+ New-Item -ItemType Directory -Force -Path (Split-Path $RecipePath) | Out-Null
496
+ [System.IO.File]::WriteAllText($RecipePath, ($recipe | ConvertTo-Json -Depth 8), (New-Object System.Text.UTF8Encoding $false))
497
+ Write-Host " Doubao MCP connector recipe -> $RecipePath"
498
+ Write-Host ' Register once in the Doubao app (自定义连接器, 传输类型 STDIO):'
499
+ Write-Host ' 服务器名称: argo'
500
+ Write-Host ' 命令: node'
501
+ Write-Host " 参数: $argoServerSlash"
502
+ Write-Host ' (workspace: follows the workspace selected in Doubao)'
503
+ if ($BridgePath) {
504
+ Write-Host ' 服务器名称: graph-mcp'
505
+ Write-Host ' 命令: node'
506
+ Write-Host " 参数: $($BridgePath -replace '\\', '/')"
507
+ Write-Host " 环境变量: GRAPH_MCP_URL=$GraphMcpUrl"
508
+ }
509
+ }
510
+
375
511
  function Write-OpenClawMcpConfig {
376
512
  # Register the argo MCP server under mcp.servers.argo in
377
513
  # ~/.openclaw/openclaw.json. OpenClaw is a fixed-workspace host: its
@@ -491,200 +627,51 @@ function Write-DshManagedBlock {
491
627
  }
492
628
 
493
629
  function New-DshWakeupPlugin {
494
- # Generate the DSH wakeup-gate Cordis plugin under ~/.dsh/plugins from the
495
- # <WakeupGuideline> block of the rule file. This is the DeepSeek Harness
496
- # equivalent of the OpenCode hook plugin argo/plugins/argo-wakeup.js: it
497
- # registers the gate as the first system-prompt section after the harness
498
- # identity (order -100), before the deployment persona (order 0).
630
+ # Deploy the DSH wakeup-gate Cordis plugin under ~/.dsh/plugins by copying
631
+ # the single-source bundle artifact dsh-argo-wakeup/index.js (generated from
632
+ # the <WakeupGuideline> block of argo/rules/archgraph.instructions.md by
633
+ # scripts/gen-dsh-plugins.js). Copying - not regenerating a template here -
634
+ # keeps the deployed plugin and the shipped bundle byte-identical, so the
635
+ # gate text has exactly one source and cannot fork.
499
636
  param(
500
- [string]$DshHome,
501
- [string]$RuleText
637
+ [string]$DshHome
502
638
  )
503
- $gate = Get-WakeupGuideline -RuleText $RuleText
504
- if (-not $gate) {
505
- Write-Warning ' <WakeupGuideline> not found in the rule file; DSH wakeup plugin skipped.'
639
+ $source = Join-Path (Join-Path $repoRoot 'dsh-argo-wakeup') 'index.js'
640
+ if (-not (Test-Path $source)) {
641
+ Write-Warning " $source not found; DSH wakeup plugin skipped."
506
642
  return $null
507
643
  }
508
644
  $dir = Join-Path (Join-Path $DshHome 'plugins') 'dsh-argo-wakeup'
509
645
  New-Item -ItemType Directory -Force -Path $dir | Out-Null
510
- $gateJson = $gate | ConvertTo-Json
511
- $plugin = @"
512
- // dsh-argo-wakeup - generated by install-argo.ps1 from
513
- // argo/rules/archgraph.instructions.md (single source of truth: the rule file;
514
- // this file is a deployment artifact, do not edit by hand).
515
- // DeepSeek Harness equivalent of the OpenCode hook argo/plugins/argo-wakeup.js:
516
- // registers the unconditional wakeup gate as the first system-prompt section
517
- // after the harness identity, so every session identifies its Business Actor
518
- // through the argo MCP server before responding.
519
- export const name = 'dsh-argo-wakeup'
520
- export const inject = ['systemPrompt']
521
- const WAKEUP_GATE = $gateJson
522
- export function apply(ctx) {
523
- ctx.effect(() => ctx.systemPrompt.section({
524
- name: 'argo:wakeup',
525
- order: -90,
526
- text: WAKEUP_GATE,
527
- }), 'argo:wakeup.section()')
528
- }
529
- "@
530
646
  $indexPath = Join-Path $dir 'index.js'
531
- [System.IO.File]::WriteAllText($indexPath, $plugin, (New-Object System.Text.UTF8Encoding $false))
532
- Write-Host " DSH wakeup plugin generated -> $indexPath"
647
+ Copy-Item -Force -Path $source -Destination $indexPath
648
+ Write-Host " DSH wakeup plugin <- $source (single source)"
533
649
  return $indexPath
534
650
  }
535
651
 
536
652
  function New-DshWorkspaceBridge {
537
- # Generate the DSH workspace bridge plugin under ~/.dsh/plugins. It
538
- # connects directly to the argo MCP server (no dsh-mcp-client row needed)
539
- # with a zero-dependency minimal MCP stdio client, registers every tool as
653
+ # Deploy the DSH workspace bridge plugin under ~/.dsh/plugins by copying the
654
+ # single-source bundle artifact dsh-argo-workspace/index.js. It connects
655
+ # directly to the argo MCP server (no dsh-mcp-client row needed) with a
656
+ # zero-dependency minimal MCP stdio client, registers every tool as
540
657
  # mcp__argo__* and injects the current session's workspace directory
541
658
  # (SessionHeader.cwd) as the per-call `workspaceRoot`, so ONE dsh instance
542
659
  # follows whichever workspace the user switched to - no model-visible
543
- # parameters, no internal tool names, no restart. The argo server honors
544
- # the injected workspaceRoot unconditionally.
660
+ # parameters, no internal tool names, no restart. Copying (not embedding a
661
+ # template) keeps the deployed plugin and the shipped bundle identical.
545
662
  param(
546
663
  [string]$DshHome
547
664
  )
665
+ $source = Join-Path (Join-Path $repoRoot 'dsh-argo-workspace') 'index.js'
666
+ if (-not (Test-Path $source)) {
667
+ Write-Warning " $source not found; DSH workspace bridge skipped."
668
+ return $null
669
+ }
548
670
  $dir = Join-Path (Join-Path $DshHome 'plugins') 'dsh-argo-workspace'
549
671
  New-Item -ItemType Directory -Force -Path $dir | Out-Null
550
- $plugin = @'
551
- // dsh-argo-workspace - generated by install-argo.ps1 (single source of truth:
552
- // the installer; this file is a deployment artifact, do not edit by hand).
553
- //
554
- // Direct MCP bridge to the argo server for DeepSeek Harness. Registers every
555
- // argo tool as mcp__argo__* and injects the current session's workspace
556
- // directory (SessionHeader.cwd) as the per-call `workspaceRoot` argument, so
557
- // one dsh instance follows whichever workspace the user switched to - the
558
- // model sees no extra parameters and no internal tool names. The argo server
559
- // honors the injected workspaceRoot unconditionally.
560
- //
561
- // Zero dependencies on purpose: implements the minimal MCP stdio client
562
- // (JSON-RPC 2.0, one JSON object per line) with Node built-ins only, so the
563
- // plugin runs from any DSH layout without resolving @modelcontextprotocol/sdk.
564
- import { spawn } from 'node:child_process'
565
- import readline from 'node:readline'
566
-
567
- export const name = 'dsh-argo-workspace'
568
- export const inject = ['tools']
569
-
570
- /** Minimal MCP stdio client over the argo server process. */
571
- function createArgoClient(serverPath, env, cwd) {
572
- const child = spawn('node', [serverPath], {
573
- stdio: ['pipe', 'pipe', 'pipe'],
574
- env,
575
- ...(cwd ? { cwd } : {}),
576
- })
577
- const pending = new Map()
578
- let nextId = 1
579
- readline.createInterface({ input: child.stdout }).on('line', (line) => {
580
- let message
581
- try { message = JSON.parse(line) } catch { return }
582
- if (message && typeof message.id === 'number' && pending.has(message.id)) {
583
- const { resolve, reject } = pending.get(message.id)
584
- pending.delete(message.id)
585
- if (message.error) reject(new Error(JSON.stringify(message.error)))
586
- else resolve(message.result)
587
- }
588
- })
589
- child.stderr.on('data', () => {}) // drain; the argo server logs to stderr
590
- const request = (method, params) => new Promise((resolve, reject) => {
591
- const id = nextId++
592
- pending.set(id, { resolve, reject })
593
- child.stdin.write(JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\n')
594
- })
595
- return {
596
- request,
597
- notify: (method, params) => {
598
- child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method, params }) + '\n')
599
- },
600
- close: () => child.kill(),
601
- }
602
- }
603
-
604
- /** Connect, list tools, register them, and keep the client until disposal. */
605
- export async function apply(ctx, config) {
606
- const serverPath = config.serverPath
607
- const workspaces = Array.isArray(config.workspaces) ? config.workspaces : []
608
- const env = { ...process.env }
609
- if (workspaces.length > 0) env.ARGO_WORKSPACE_ROOTS = workspaces.join(';')
610
- const client = createArgoClient(serverPath, env, config.cwd)
611
- ctx.effect(() => () => client.close(), 'dsh-argo-workspace.dispose()')
612
-
613
- let tools = []
614
- try {
615
- await client.request('initialize', {
616
- protocolVersion: '2024-11-05',
617
- capabilities: {},
618
- clientInfo: { name: 'dsh-argo-workspace', version: '0.1.0' },
619
- })
620
- client.notify('notifications/initialized', {})
621
- const listed = await client.request('tools/list', {})
622
- tools = (listed && Array.isArray(listed.tools)) ? listed.tools : []
623
- } catch (error) {
624
- console.warn(`[dsh-argo-workspace] failed to connect to the argo MCP server (${serverPath}): ${error && error.message ? error.message : error}`)
625
- return
626
- }
627
-
628
- const disposers = []
629
- for (const tool of tools) {
630
- const publicName = 'mcp__argo__' + tool.name
631
- disposers.push(ctx.tools.register({
632
- name: publicName,
633
- description: tool.description ?? '',
634
- parameters: tool.inputSchema,
635
- output: {
636
- schema: {
637
- type: 'object',
638
- properties: {
639
- content: { type: 'array', items: {} },
640
- structuredContent: {},
641
- },
642
- required: ['content'],
643
- additionalProperties: false,
644
- },
645
- render: (_args, value) => value.content,
646
- },
647
- execute: async (args, exec) => {
648
- // SessionHeader.cwd (the durable session workspace), NOT
649
- // requestHeader() — that returns the request EpochHeader
650
- // (config/system/tools) which has no cwd field.
651
- const sessionCwd = exec && exec.agent && exec.agent.session
652
- ? exec.agent.session.header?.cwd
653
- : undefined
654
- const injected = { ...(args && typeof args === 'object' ? args : {}) }
655
- if (typeof sessionCwd === 'string' && sessionCwd !== '') {
656
- injected.workspaceRoot = sessionCwd
657
- }
658
- if (exec && exec.signal && exec.signal.aborted) {
659
- throw new Error('aborted')
660
- }
661
- const result = await client.request('tools/call', {
662
- name: tool.name,
663
- arguments: injected,
664
- })
665
- const text = Array.isArray(result.content)
666
- ? result.content
667
- .map((block) => block && block.type === 'text' && typeof block.text === 'string'
668
- ? block.text
669
- : JSON.stringify(block))
670
- .join('\n')
671
- : (result.toolResult !== undefined ? JSON.stringify(result.toolResult) : '(no output)')
672
- if (result.isError === true) throw new Error(text)
673
- return {
674
- content: [{ type: 'text', text }],
675
- ...(result.structuredContent !== undefined ? { structuredContent: result.structuredContent } : {}),
676
- }
677
- },
678
- }))
679
- }
680
- ctx.effect(() => () => {
681
- for (const dispose of disposers) dispose()
682
- }, 'dsh-argo-workspace.tools')
683
- }
684
- '@
685
672
  $indexPath = Join-Path $dir 'index.js'
686
- [System.IO.File]::WriteAllText($indexPath, $plugin, (New-Object System.Text.UTF8Encoding $false))
687
- Write-Host " DSH workspace bridge generated -> $indexPath"
673
+ Copy-Item -Force -Path $source -Destination $indexPath
674
+ Write-Host " DSH workspace bridge <- $source (single source)"
688
675
  return $indexPath
689
676
  }
690
677
 
@@ -867,8 +854,8 @@ if ($SkipDsh) {
867
854
  Write-Host ' argo\skills\agent-search-diagnosis -> $DshHome\skills\agent-search-diagnosis (DeepSeek Harness skill)'
868
855
  Copy-Tree -Source $diagSkillSrc -Destination (Join-Path (Join-Path $DshHome 'skills') 'agent-search-diagnosis')
869
856
 
870
- Write-Host "[17/22] argo\rules\<WakeupGuideline> -> $DshHome\plugins\dsh-argo-wakeup\index.js (DeepSeek Harness wakeup plugin)"
871
- $wakeupDshPath = New-DshWakeupPlugin -DshHome $DshHome -RuleText $ruleSrcContent
857
+ Write-Host "[17/22] dsh-argo-wakeup\index.js (single source; gate from argo\rules\archgraph.instructions.md <WakeupGuideline>) -> $DshHome\plugins\dsh-argo-wakeup\index.js (DeepSeek Harness wakeup plugin)"
858
+ $wakeupDshPath = New-DshWakeupPlugin -DshHome $DshHome
872
859
 
873
860
  Write-Host "[18/22] argo-workspace + argo-wakeup rows -> $patchPath (DeepSeek Harness MCP bridge + wakeup plugin)"
874
861
  # The generated dsh-argo-workspace bridge connects directly to the argo
@@ -937,6 +924,48 @@ Copy-Tree -Source $diagSkillSrc -Destination (Join-Path (Join-Path $OpenClawHome
937
924
  Write-Host ' the OpenClaw gateway (openclaw gateway restart) if it is already running.'
938
925
  }
939
926
 
927
+ if ($SkipDoubao) {
928
+ Write-Host 'Skipped Doubao integration (-SkipDoubao).'
929
+ } else {
930
+ # Doubao (desktop agent mode) skill discovery. Doubao adopts the Anthropic
931
+ # Agent Skills spec and loads user skills from
932
+ # <workspace>/.user_skills/<name>/SKILL.md (per-session workspace root)
933
+ # plus a global user root
934
+ # ~/Doubao/skills/<name>/SKILL.md
935
+ # Doubao exposes no AGENTS.md-equivalent always-on instruction file, so the
936
+ # WakeupGuideline / unconditional startup gate has no hook (skills are the
937
+ # fully ported surface). MCP servers are registered through Doubao's in-app
938
+ # custom connector UI (STDIO), not a config file, so the installer emits a
939
+ # copy-paste connector recipe instead of writing a config.
940
+ $doubaoSkills = @('argo-init', 'ea-human-reconcile', 'agent-search-diagnosis')
941
+ $doubaoSkillsSrc = Join-Path $argoDir 'skills'
942
+ Write-Host '==> Deploying Doubao (desktop agent mode) integration'
943
+ Copy-DoubaoSkills -Root (Join-Path $DoubaoWorkspace '.user_skills') -SourceSkillsRoot $doubaoSkillsSrc -SkillNames $doubaoSkills -Label 'workspace .user_skills'
944
+ Copy-DoubaoSkills -Root (Join-Path $DoubaoHome 'skills') -SourceSkillsRoot $doubaoSkillsSrc -SkillNames $doubaoSkills -Label 'global ~/Doubao/skills'
945
+ # Entry skill: the single-source ARGO rules packaged as a Doubao skill whose
946
+ # always-in-context description states the STEP 0 gate and the mandate to
947
+ # load it before any intent-graph read/write. This is the closest Doubao
948
+ # allows to an always-on rule (skills have no system-prompt hook).
949
+ $doubaoRule = Join-Path $argoDir 'rules\archgraph.instructions.md'
950
+ foreach ($doubaoRoot in @((Join-Path $DoubaoWorkspace '.user_skills'), (Join-Path $DoubaoHome 'skills'))) {
951
+ $entryDir = Join-Path $doubaoRoot 'archgraph-argo'
952
+ New-Item -ItemType Directory -Force -Path $entryDir | Out-Null
953
+ Convert-RuleToSkill -RuleFile $doubaoRule -DestinationFile (Join-Path $entryDir 'SKILL.md')
954
+ Write-Host " entry skill (ARGO rules) -> $(Join-Path $entryDir 'SKILL.md')"
955
+ }
956
+ Write-Host ' Doubao injects each skill''s name + description into context and loads the'
957
+ Write-Host ' body on trigger; new skills are picked up on the next agent session.'
958
+ $doubaoBridgeDir = Join-Path $ArgoRoot 'mcp-bridges'
959
+ Copy-Tree -Source (Join-Path $argoDir 'mcp-bridges') -Destination $doubaoBridgeDir
960
+ $doubaoBridgePath = Join-Path $doubaoBridgeDir 'graph-mcp-stdio.js'
961
+ if (-not (Test-Path $doubaoBridgePath)) { $doubaoBridgePath = '' }
962
+ Write-DoubaoMcpRecipe -RecipePath (Join-Path $ArgoRoot 'doubao-mcp.json') -ArgoServer (Join-Path $ArgoRoot 'scripts\argo-mcp-server.js') -BridgePath $doubaoBridgePath -GraphMcpUrl $GraphMcpUrl
963
+ Write-Host ' the argo connector has no fixed workspace: it follows the workspace you'
964
+ Write-Host ' select in Doubao (MCP roots / connector workingDirectory), like OpenCode/DSH.'
965
+ Write-Host ' note: Doubao has no AGENTS.md-equivalent always-on rule file, so the ARGO'
966
+ Write-Host ' WakeupGuideline / unconditional startup gate is not deployed (no hook).'
967
+ }
968
+
940
969
  if ($SkipDeps) {
941
970
  Write-Host 'Skipped dependency install (-SkipDeps).'
942
971
  } elseif (Get-Command npm -ErrorAction SilentlyContinue) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "archgraph-argo",
3
- "version": "0.26.2",
3
+ "version": "0.27.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": {
@@ -45,7 +45,10 @@
45
45
  "playwright": "1.61.1"
46
46
  },
47
47
  "scripts": {
48
- "test": "node --test \"tests/*.test.js\""
48
+ "test": "node --test \"tests/*.test.js\"",
49
+ "acceptance": "node scripts/mcp-acceptance.js",
50
+ "gen:dsh-plugins": "node scripts/gen-dsh-plugins.js",
51
+ "prepack": "node scripts/gen-dsh-plugins.js"
49
52
  },
50
53
  "engines": {
51
54
  "node": ">=18"