@joekytc/dsh-swarm 0.1.2 → 0.3.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 +177 -140
- package/README.zh-CN.md +173 -126
- package/client/BoardCard.tsx +24 -2
- package/client/ConfigSection.tsx +162 -0
- package/client/ConfigSelect.tsx +71 -0
- package/client/KanbanBoard.tsx +3 -0
- package/client/KanbanTab.tsx +4 -3
- package/client/TaskDrawer.tsx +4 -26
- package/client/WorkflowRail.tsx +3 -1
- package/client/config-store.ts +92 -0
- package/client/config.css +110 -0
- package/client/index.ts +39 -4
- package/client/kanban.css +88 -2
- package/client/session-bridge.ts +39 -0
- package/client/timeline-model.ts +12 -1
- package/client/workflow-model.ts +3 -1
- package/lib/client.js +519 -56
- package/lib/config.d.ts +26 -2
- package/lib/config.js +20 -1
- package/lib/dispatcher/agent-runner.d.ts +37 -7
- package/lib/dispatcher/agent-runner.js +239 -86
- package/lib/dispatcher/chain-auditor.d.ts +4 -4
- package/lib/dispatcher/chain-auditor.js +14 -9
- package/lib/dispatcher/dispatcher.d.ts +69 -10
- package/lib/dispatcher/dispatcher.js +281 -42
- package/lib/dispatcher/event-waker.d.ts +1 -1
- package/lib/dispatcher/event-waker.js +2 -2
- package/lib/dispatcher/git-credentials.d.ts +2 -2
- package/lib/dispatcher/git-credentials.js +2 -2
- package/lib/dispatcher/model-candidates.d.ts +1 -1
- package/lib/dispatcher/model-candidates.js +1 -1
- package/lib/dispatcher/session-events.d.ts +12 -16
- package/lib/dispatcher/session-events.js +18 -6
- package/lib/dispatcher/target-repo.d.ts +2 -2
- package/lib/dispatcher/target-repo.js +3 -3
- package/lib/dispatcher/v-orchestrator.d.ts +44 -11
- package/lib/dispatcher/v-orchestrator.js +257 -49
- package/lib/dispatcher/watchdog.d.ts +1 -1
- package/lib/dispatcher/watchdog.js +2 -2
- package/lib/domain/config-override.d.ts +52 -0
- package/lib/domain/config-override.js +138 -0
- package/lib/domain/delivery-contract.d.ts +4 -3
- package/lib/domain/delivery-contract.js +30 -18
- package/lib/domain/delivery-evidence.d.ts +1 -1
- package/lib/domain/delivery-evidence.js +1 -1
- package/lib/domain/event-store.js +1 -1
- package/lib/domain/gate-policy.d.ts +26 -0
- package/lib/domain/gate-policy.js +44 -0
- package/lib/domain/im-message.d.ts +15 -0
- package/lib/domain/im-message.js +149 -0
- package/lib/domain/kanban-service.d.ts +28 -12
- package/lib/domain/kanban-service.js +73 -30
- package/lib/domain/memory.js +1 -1
- package/lib/domain/ocr-review.d.ts +47 -0
- package/lib/domain/ocr-review.js +105 -0
- package/lib/domain/permissions.js +6 -6
- package/lib/domain/planning-checklist.d.ts +5 -0
- package/lib/domain/planning-checklist.js +80 -6
- package/lib/domain/projection.js +8 -7
- package/lib/domain/review-evidence.js +1 -1
- package/lib/domain/state-machine.js +3 -2
- package/lib/domain/task-parents.js +1 -1
- package/lib/domain/types.d.ts +5 -5
- package/lib/index.js +28 -25
- package/lib/roles/clean-fs-tools.d.ts +22 -0
- package/lib/roles/clean-fs-tools.js +117 -0
- package/lib/roles/preset-installer.js +3 -3
- package/lib/roles/skill-installer.d.ts +6 -0
- package/lib/roles/skill-installer.js +32 -0
- package/lib/roles/toolsets.d.ts +71 -15
- package/lib/roles/toolsets.js +418 -68
- package/lib/roles/wiki-worker.d.ts +1 -0
- package/lib/roles/wiki-worker.js +12 -4
- package/lib/routes/kanban-http.d.ts +28 -2
- package/lib/routes/kanban-http.js +199 -6
- package/lib/routes/kanban-sse.d.ts +1 -1
- package/lib/routes/kanban-sse.js +1 -1
- package/lib/routes/planning-driver.d.ts +6 -2
- package/lib/routes/planning-driver.js +15 -7
- package/lib/routes/prefix-router.d.ts +19 -3
- package/lib/routes/prefix-router.js +40 -3
- package/lib/services/config-provider.d.ts +38 -0
- package/lib/services/config-provider.js +92 -0
- package/lib/services/gate-runner.d.ts +24 -0
- package/lib/services/gate-runner.js +87 -0
- package/lib/services/im-delivery.d.ts +94 -0
- package/lib/services/im-delivery.js +263 -0
- package/lib/services/kanban-provider.d.ts +6 -2
- package/lib/services/kanban-provider.js +41 -3
- package/lib/services/llm-catalog.d.ts +35 -0
- package/lib/services/llm-catalog.js +19 -0
- package/lib/services/ocr-cli.d.ts +35 -0
- package/lib/services/ocr-cli.js +128 -0
- package/lib/tools/kanban-tools.d.ts +2 -2
- package/lib/tools/kanban-tools.js +2 -1
- package/lib/tools/main-session-tools.d.ts +22 -3
- package/lib/tools/main-session-tools.js +135 -30
- package/lib/tools/ocr-review-tools.d.ts +11 -0
- package/lib/tools/ocr-review-tools.js +63 -0
- package/lib/tools/planning-tools.d.ts +8 -1
- package/lib/tools/planning-tools.js +44 -15
- package/lib/tools/prefetch-tools.js +1 -0
- package/lib/tools/spec-card-tools.js +1 -0
- package/lib/tools/wiki-tools.js +6 -5
- package/lib/wiki/kb-linkage.d.ts +9 -2
- package/lib/wiki/kb-linkage.js +3 -3
- package/lib/wiki/local-kb-client.d.ts +14 -0
- package/lib/wiki/local-kb-client.js +101 -0
- package/lib/wiki/local-kb.d.ts +6 -0
- package/lib/wiki/local-kb.js +25 -0
- package/lib/wiki/memory-recall.d.ts +14 -6
- package/lib/wiki/memory-recall.js +17 -13
- package/lib/wiki/page-path.d.ts +9 -3
- package/lib/wiki/page-path.js +33 -12
- package/lib/wiki/wiki-vault-client.d.ts +3 -3
- package/lib/wiki/wiki-vault-client.js +6 -6
- package/package.json +16 -11
- package/personas/kanban-d/agent.cordis.yml +5 -5
- package/personas/kanban-d/preset.yml +1 -1
- package/personas/kanban-dt/agent.cordis.yml +25 -7
- package/personas/kanban-dt/preset.yml +1 -1
- package/personas/kanban-p/agent.cordis.yml +19 -3
- package/personas/kanban-p/preset.yml +1 -1
- package/personas/kanban-pt/agent.cordis.yml +39 -9
- package/personas/kanban-pt/preset.yml +1 -1
- package/personas/kanban-v/agent.cordis.yml +3 -3
- package/personas/kanban-w/agent.cordis.yml +37 -18
- package/personas/kanban-w/preset.yml +1 -1
- package/personas/persona-d.md +1 -1
- package/personas/persona-dt.md +13 -5
- package/personas/persona-p.md +5 -2
- package/personas/persona-pt.md +13 -6
- package/personas/persona-v.md +2 -2
- package/personas/persona-w.md +11 -9
- package/personas/swarm/agent.cordis.yml +43 -0
- package/personas/swarm/preset.yml +5 -0
- package/skills/grill-me/SKILL.md +71 -0
- package/skills/llm-wiki-skill/.mise.toml +2 -0
- package/skills/llm-wiki-skill/.nvmrc +1 -0
- package/skills/llm-wiki-skill/AGENTS.md +173 -0
- package/skills/llm-wiki-skill/CHANGELOG.md +548 -0
- package/skills/llm-wiki-skill/CLAUDE.md +152 -0
- package/skills/llm-wiki-skill/HERMES.md +44 -0
- package/skills/llm-wiki-skill/README.en.md +261 -0
- package/skills/llm-wiki-skill/README.md +291 -0
- package/skills/llm-wiki-skill/SKILL.md +1133 -0
- package/skills/llm-wiki-skill/assets/graph-demo.gif +0 -0
- package/skills/llm-wiki-skill/assets/graph-preview.png +0 -0
- package/skills/llm-wiki-skill/deps/LICENSE-d3.txt +13 -0
- package/skills/llm-wiki-skill/deps/LICENSE-marked.txt +44 -0
- package/skills/llm-wiki-skill/deps/LICENSE-purify.txt +568 -0
- package/skills/llm-wiki-skill/deps/LICENSE-roughjs.txt +21 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/SKILL.md +261 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/references/config/first-time-setup.md +106 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/cdp.ts +179 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/constants.ts +13 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/defuddle-converter.ts +58 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/html-to-markdown.ts +135 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/legacy-converter.ts +629 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/main.ts +314 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/markdown-conversion-shared.ts +305 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/media-localizer.ts +317 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/package.json +14 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/paths.ts +29 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/package.json +9 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.test.ts +307 -0
- package/skills/llm-wiki-skill/deps/baoyu-url-to-markdown/scripts/vendor/baoyu-chrome-cdp/src/index.ts +523 -0
- package/skills/llm-wiki-skill/deps/d3.min.js +2 -0
- package/skills/llm-wiki-skill/deps/marked.min.js +6 -0
- package/skills/llm-wiki-skill/deps/purify.min.js +3 -0
- package/skills/llm-wiki-skill/deps/rough.min.js +7 -0
- package/skills/llm-wiki-skill/deps/youtube-transcript/SKILL.md +47 -0
- package/skills/llm-wiki-skill/deps/youtube-transcript/scripts/get_transcript.py +72 -0
- package/skills/llm-wiki-skill/designs/graph-edge-legibility/graph-edge-treatments.html +480 -0
- package/skills/llm-wiki-skill/docs/design/oriental-atlas/DESIGN.md +183 -0
- package/skills/llm-wiki-skill/docs/design/oriental-atlas/README.md +10 -0
- package/skills/llm-wiki-skill/docs/design/oriental-atlas/design-brief.md +170 -0
- package/skills/llm-wiki-skill/docs/design/oriental-atlas/oriental-editorial-atlas.html +1908 -0
- package/skills/llm-wiki-skill/docs/design/oriental-atlas/reviews/result-review.md +68 -0
- package/skills/llm-wiki-skill/docs/graph/2026-06-16-interaction-risk-audit.md +88 -0
- package/skills/llm-wiki-skill/docs/graph/2026-06-16-interaction-test-coverage-map.md +212 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-0-2-baseline.md +86 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-1-3-dom-svg-large-baseline.md +85 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-1-4-disposable-validation-gate.md +97 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-18-phase-2-4-global-renderer-trial-matrix.md +168 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-1-sigma-graphology-trial.md +71 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-2-vis-network-trial.md +78 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-3-aggregation-fallback-trial.md +72 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-phase-6-4-global-renderer-route-decision.md +94 -0
- package/skills/llm-wiki-skill/docs/graph/performance/2026-06-19-sigma-global-production-integration-result.md +102 -0
- package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.json +9 -0
- package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-dense-wheel.png +0 -0
- package/skills/llm-wiki-skill/docs/graph/performance/artifacts/2026-06-18-phase-0-2/stage-4.5-offline-navigation.png +0 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-15-omp-tool-status-events-design.md +174 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-16-graph-interaction-geometry-design.md +832 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-16-graph-six-layer-architecture-design.md +577 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-17-static-renderer-coordination-split-design.md +172 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-18-large-graph-global-community-design.md +909 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-19-sigma-global-graph-renderer-design.md +360 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-20-paper-ui-port-design.md +162 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-20-paper-ui-v2-shell-alignment-design.md +384 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-21-graph-experience-completion-design.md +534 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-22-chat-auto-scroll-design.md +185 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-22-graph-community-node-visual-design.md +266 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-25-sigma-overlay-refactor-perf-design.md +170 -0
- package/skills/llm-wiki-skill/docs/spark/2026-06-26-global-sigma-community-spotlight-design.md +393 -0
- package/skills/llm-wiki-skill/docs/spark/mockups/2026-06-18-large-graph-global-community-flow.html +746 -0
- package/skills/llm-wiki-skill/install.ps1 +87 -0
- package/skills/llm-wiki-skill/install.sh +722 -0
- package/skills/llm-wiki-skill/package-lock.json +11171 -0
- package/skills/llm-wiki-skill/package.json +24 -0
- package/skills/llm-wiki-skill/packages/graph-engine/package.json +37 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/anim/.gitkeep +1 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/anim/index.ts +179 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/architecture.ts +79 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/diff.ts +121 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/facade.ts +1406 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/graph-node.ts +37 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/index.ts +25 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/layout/edge-geometry.ts +17 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/layout/index.ts +16 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/layout/spatial-index.ts +509 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/atlas.ts +18 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/index.ts +10 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/labels.ts +11 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/layout.ts +81 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/learning.ts +8 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/legacy-helpers.ts +1379 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/queue.ts +7 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/storage.ts +4 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/model/visibility.ts +9 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/.gitkeep +1 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/adapter.ts +443 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/aggregation-containers.ts +64 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-cloud-geometry.ts +178 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-wash.ts +238 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/community-washes.ts +19 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/compat-contract.ts +14 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/controller.ts +705 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/controls.ts +288 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/dom-svg-renderer.ts +180 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/edges.ts +51 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/geometry.ts +380 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/gestures.ts +673 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/graph-renderer-root.ts +387 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/hit-testing.ts +56 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/host-dom.ts +14 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/hover-card.ts +37 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/index.ts +213 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/keyboard.ts +48 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/legend.ts +25 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/minimap.ts +45 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/model.ts +1339 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/node-drag-lifecycle.ts +94 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/nodes.ts +103 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/offline-reader.ts +209 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/overlays-presenter.ts +192 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/overlays.ts +73 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/pin-position.ts +51 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/preview.ts +65 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/relation-focus.ts +91 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-context.ts +85 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-pipeline.ts +871 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/render-styles.ts +1405 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/renderer-surface.ts +75 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/search.ts +57 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-coordinates.ts +44 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-global-drag.ts +246 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-global-renderer.ts +1425 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/sigma-overlay-svg.ts +121 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/simulation-bridge.ts +59 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/state.ts +262 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/toolbar.ts +40 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/render/viewport.ts +336 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/select/.gitkeep +1 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/select/index.ts +189 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/sim/index.ts +372 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/sim/pins.ts +84 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/summary/index.ts +447 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/themes/.gitkeep +1 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/themes/index.ts +8 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/themes/tokens.ts +117 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/types/d3-quadtree.d.ts +22 -0
- package/skills/llm-wiki-skill/packages/graph-engine/src/types.ts +531 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/aggregation-fallback-trial-adapter.test.ts +115 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/aggregation-fallback-trial-adapter.ts +222 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/anim.test.ts +121 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/architecture.test.ts +63 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/community-cloud-geometry.test.ts +86 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/community-wash.test.ts +97 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/diff.test.ts +133 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/facade.test.ts +1369 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/geometry.test.ts +147 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/gestures.test.ts +768 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/graph-layout.test.ts +110 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/helpers.test.ts +287 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/interaction-contract.test.ts +106 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/keyboard.test.ts +59 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/large-fixtures.test.ts +47 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/large-graph-fixtures.ts +420 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/learning.test.ts +259 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/node-drag-lifecycle.test.ts +166 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/overlays.test.ts +115 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/preview.test.ts +56 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/queue.test.ts +114 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/relation-focus.test.ts +115 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/render-model.test.ts +1030 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-adapter-contract.test.ts +271 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-boundary.test.ts +618 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/renderer-lifecycle.test.ts +1711 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/route-continuity.test.ts +284 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/runtime-state.test.ts +281 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/search-and-legend.test.ts +124 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/select.test.ts +168 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-coordinates.test.ts +50 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-global-renderer.test.ts +2210 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-trial-adapter.test.ts +82 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/sigma-trial-adapter.ts +271 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/sim.test.ts +207 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/simulation-bridge.test.ts +96 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/spatial-index.test.ts +222 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/state.test.ts +189 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/summary-contract.test.ts +422 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/themes.test.ts +62 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/toolbar.test.ts +64 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/viewport.test.ts +213 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/vis-network-trial-adapter.test.ts +82 -0
- package/skills/llm-wiki-skill/packages/graph-engine/test/vis-network-trial-adapter.ts +186 -0
- package/skills/llm-wiki-skill/packages/graph-engine/tsconfig.json +17 -0
- package/skills/llm-wiki-skill/packages/graph-engine/vite.config.ts +15 -0
- package/skills/llm-wiki-skill/platforms/claude/CLAUDE.md +37 -0
- package/skills/llm-wiki-skill/platforms/claude/companions/llm-wiki-upgrade/SKILL.md +95 -0
- package/skills/llm-wiki-skill/platforms/codex/AGENTS.md +23 -0
- package/skills/llm-wiki-skill/platforms/hermes/README.md +31 -0
- package/skills/llm-wiki-skill/platforms/openclaw/README.md +31 -0
- package/skills/llm-wiki-skill/scripts/adapter-state.sh +424 -0
- package/skills/llm-wiki-skill/scripts/build-graph-data.sh +395 -0
- package/skills/llm-wiki-skill/scripts/build-graph-html.sh +459 -0
- package/skills/llm-wiki-skill/scripts/cache.sh +352 -0
- package/skills/llm-wiki-skill/scripts/create-source-page.sh +100 -0
- package/skills/llm-wiki-skill/scripts/delete-helper.sh +68 -0
- package/skills/llm-wiki-skill/scripts/graph-analysis.js +732 -0
- package/skills/llm-wiki-skill/scripts/hook-session-start.sh +46 -0
- package/skills/llm-wiki-skill/scripts/init-wiki.sh +95 -0
- package/skills/llm-wiki-skill/scripts/lib/source-signal-eligibility.js +158 -0
- package/skills/llm-wiki-skill/scripts/lint-fix.sh +114 -0
- package/skills/llm-wiki-skill/scripts/lint-runner.sh +217 -0
- package/skills/llm-wiki-skill/scripts/runtime-context.sh +77 -0
- package/skills/llm-wiki-skill/scripts/shared-config.sh +83 -0
- package/skills/llm-wiki-skill/scripts/source-record-contract.tsv +10 -0
- package/skills/llm-wiki-skill/scripts/source-registry.sh +349 -0
- package/skills/llm-wiki-skill/scripts/source-registry.tsv +10 -0
- package/skills/llm-wiki-skill/scripts/source-signal-coverage.js +83 -0
- package/skills/llm-wiki-skill/scripts/validate-step1.sh +144 -0
- package/skills/llm-wiki-skill/scripts/wiki-compat.sh +267 -0
- package/skills/llm-wiki-skill/setup.sh +8 -0
- package/skills/llm-wiki-skill/templates/entity-template.md +30 -0
- package/skills/llm-wiki-skill/templates/graph-styles/wash/footer.html +27 -0
- package/skills/llm-wiki-skill/templates/graph-styles/wash/graph-wash-helpers.js +1326 -0
- package/skills/llm-wiki-skill/templates/graph-styles/wash/graph-wash.js +1009 -0
- package/skills/llm-wiki-skill/templates/graph-styles/wash/header.html +2002 -0
- package/skills/llm-wiki-skill/templates/index-en-template.md +51 -0
- package/skills/llm-wiki-skill/templates/index-template.md +51 -0
- package/skills/llm-wiki-skill/templates/log-en-template.md +11 -0
- package/skills/llm-wiki-skill/templates/log-template.md +11 -0
- package/skills/llm-wiki-skill/templates/overview-en-template.md +41 -0
- package/skills/llm-wiki-skill/templates/overview-template.md +41 -0
- package/skills/llm-wiki-skill/templates/purpose-en-template.md +16 -0
- package/skills/llm-wiki-skill/templates/purpose-template.md +16 -0
- package/skills/llm-wiki-skill/templates/query-template.md +19 -0
- package/skills/llm-wiki-skill/templates/schema-template.md +185 -0
- package/skills/llm-wiki-skill/templates/source-template.md +51 -0
- package/skills/llm-wiki-skill/templates/synthesis-template.md +25 -0
- package/skills/llm-wiki-skill/templates/topic-template.md +35 -0
- package/skills/llm-wiki-skill/tests/adapter-state.sh +338 -0
- package/skills/llm-wiki-skill/tests/browser/graph-aggregation-fallback-trial.ts +737 -0
- package/skills/llm-wiki-skill/tests/browser/graph-community-node-map.mjs +255 -0
- package/skills/llm-wiki-skill/tests/browser/graph-community-wash-interactions.mjs +170 -0
- package/skills/llm-wiki-skill/tests/browser/graph-default-behavior.mjs +630 -0
- package/skills/llm-wiki-skill/tests/browser/graph-density-preview.mjs +53 -0
- package/skills/llm-wiki-skill/tests/browser/graph-html-insights.mjs +41 -0
- package/skills/llm-wiki-skill/tests/browser/graph-large-performance.ts +689 -0
- package/skills/llm-wiki-skill/tests/browser/graph-node-slim.mjs +75 -0
- package/skills/llm-wiki-skill/tests/browser/graph-offline-phase-6.mjs +660 -0
- package/skills/llm-wiki-skill/tests/browser/graph-renderer-trial-shared.ts +291 -0
- package/skills/llm-wiki-skill/tests/browser/graph-sigma-global-production.ts +1437 -0
- package/skills/llm-wiki-skill/tests/browser/graph-sigma-graphology-trial.ts +949 -0
- package/skills/llm-wiki-skill/tests/browser/graph-stage-4-5.mjs +815 -0
- package/skills/llm-wiki-skill/tests/browser/graph-vis-network-trial.ts +762 -0
- package/skills/llm-wiki-skill/tests/browser/graph-workbench-interactions.mjs +730 -0
- package/skills/llm-wiki-skill/tests/browser/validate-graph-trial-result.mjs +149 -0
- package/skills/llm-wiki-skill/tests/expected/graph-data-empty.json +60 -0
- package/skills/llm-wiki-skill/tests/expected/graph-data-sample.json +396 -0
- package/skills/llm-wiki-skill/tests/expected/graph-interactive-basic.html +1736 -0
- package/skills/llm-wiki-skill/tests/expected/lint-output.txt +44 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/index.md +1 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Alpha.md +10 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Beta.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Delta.md +8 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/entities/Gamma.md +8 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/queries/20260422-abc.md +10 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/synthesis/Crystal.md +8 -0
- package/skills/llm-wiki-skill/tests/fixtures/coverage-sample-wiki/wiki/topics/Overview.md +9 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-empty-wiki/wiki/entities/.gitkeep +0 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/purpose.md +3 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Attention.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Decoder.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Encoder.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/GPT.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/entities/Transformer.md +13 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/sources/paper.md +9 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/topics/arch.md +12 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-data-sample-wiki/wiki/topics/finetune.md +9 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-basic/wiki/graph-data.json +40 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-dense/wiki/graph-data.json +3965 -0
- package/skills/llm-wiki-skill/tests/fixtures/graph-interactive-multicomm/wiki/graph-data.json +212 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/index.md +14 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/C++.md +6 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Lonely.md +4 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Other.md +8 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/entities/Real.md +7 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/sources/2026-01-01-test-source.md +15 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/sources/2026-02-01-inline-img.md +12 -0
- package/skills/llm-wiki-skill/tests/fixtures/lint-sample-wiki/wiki/topics/AIbasic.md +3 -0
- package/skills/llm-wiki-skill/tests/graph-aggregation-fallback-trial.regression-1.sh +46 -0
- package/skills/llm-wiki-skill/tests/graph-analysis-helper.regression-1.sh +237 -0
- package/skills/llm-wiki-skill/tests/graph-browser-large-performance.regression-1.sh +39 -0
- package/skills/llm-wiki-skill/tests/graph-browser-stage-4-5.regression-1.sh +163 -0
- package/skills/llm-wiki-skill/tests/graph-build-failures.regression-1.sh +91 -0
- package/skills/llm-wiki-skill/tests/graph-community-node-map.regression-1.sh +107 -0
- package/skills/llm-wiki-skill/tests/graph-community-wash-interactions.regression-1.sh +35 -0
- package/skills/llm-wiki-skill/tests/graph-data-confidence-merge.regression-1.sh +309 -0
- package/skills/llm-wiki-skill/tests/graph-data-source-paths.regression-1.sh +49 -0
- package/skills/llm-wiki-skill/tests/graph-default-behavior.regression-1.sh +35 -0
- package/skills/llm-wiki-skill/tests/graph-html-a11y.regression-1.sh +50 -0
- package/skills/llm-wiki-skill/tests/graph-html-brand-link.regression-1.sh +47 -0
- package/skills/llm-wiki-skill/tests/graph-html-density.regression-1.sh +228 -0
- package/skills/llm-wiki-skill/tests/graph-html-drawer-neighbors.regression-1.sh +47 -0
- package/skills/llm-wiki-skill/tests/graph-html-insights.regression-1.sh +80 -0
- package/skills/llm-wiki-skill/tests/graph-html-long-label.regression-1.sh +92 -0
- package/skills/llm-wiki-skill/tests/graph-html-minimap.regression-1.sh +51 -0
- package/skills/llm-wiki-skill/tests/graph-html-mobile.regression-1.sh +48 -0
- package/skills/llm-wiki-skill/tests/graph-html-oriental-atlas-contract.regression-1.sh +94 -0
- package/skills/llm-wiki-skill/tests/graph-html-oriental-design-contract.regression-1.sh +82 -0
- package/skills/llm-wiki-skill/tests/graph-html-search.regression-1.sh +52 -0
- package/skills/llm-wiki-skill/tests/graph-html-styles.regression-1.sh +66 -0
- package/skills/llm-wiki-skill/tests/graph-html-toolbar.regression-1.sh +62 -0
- package/skills/llm-wiki-skill/tests/graph-offline-phase-6.regression-1.sh +51 -0
- package/skills/llm-wiki-skill/tests/graph-sigma-global-production.regression-1.sh +64 -0
- package/skills/llm-wiki-skill/tests/graph-sigma-graphology-trial.regression-1.sh +46 -0
- package/skills/llm-wiki-skill/tests/graph-vis-network-trial.regression-1.sh +46 -0
- package/skills/llm-wiki-skill/tests/graph-workbench-interactions.regression-1.sh +151 -0
- package/skills/llm-wiki-skill/tests/js/graph-wash-bootstrap.test.js +110 -0
- package/skills/llm-wiki-skill/tests/js/graph-wash-helpers.test.js +296 -0
- package/skills/llm-wiki-skill/tests/js/graph-wash-learning.test.js +260 -0
- package/skills/llm-wiki-skill/tests/js/graph-wash-queue.test.js +115 -0
- package/skills/llm-wiki-skill/tests/js/graph-wash-runtime-state.test.js +282 -0
- package/skills/llm-wiki-skill/tests/js/source-signal-coverage.test.js +48 -0
- package/skills/llm-wiki-skill/tests/js/source-signal-eligibility.test.js +202 -0
- package/skills/llm-wiki-skill/tests/lib/graph-html-engine-helpers.sh +110 -0
- package/skills/llm-wiki-skill/tests/lint-output.regression-1.sh +32 -0
- package/skills/llm-wiki-skill/tests/regression.sh +1754 -0
- package/skills/llm-wiki-skill/workbench/AGENTS.md +110 -0
- package/skills/llm-wiki-skill/workbench/CLAUDE.md +55 -0
- package/skills/llm-wiki-skill/workbench/LICENSE +21 -0
- package/skills/llm-wiki-skill/workbench/PRODUCT.md +1353 -0
- package/skills/llm-wiki-skill/workbench/README.md +30 -0
- package/skills/llm-wiki-skill/workbench/docs/current-kb-retrieval-design.md +587 -0
- package/skills/llm-wiki-skill/workbench/docs/graph-evolution-1-design.md +210 -0
- package/skills/llm-wiki-skill/workbench/docs/stage-2-design.md +1139 -0
- package/skills/llm-wiki-skill/workbench/docs/stage-3-design.md +1269 -0
- package/skills/llm-wiki-skill/workbench/docs/stage-3.5-design.md +1164 -0
- package/skills/llm-wiki-skill/workbench/docs/stage-4-design.md +504 -0
- package/skills/llm-wiki-skill/workbench/docs/stage-4.5-design.md +195 -0
- package/skills/llm-wiki-skill/workbench/docs/superpowers/specs/2026-05-28-resizable-preview-layout-design.md +165 -0
- package/skills/llm-wiki-skill/workbench/docs/superpowers/specs/2026-05-28-settings-panel-scroll-fix.md +50 -0
- package/skills/llm-wiki-skill/workbench/server/package.json +31 -0
- package/skills/llm-wiki-skill/workbench/server/src/agent.ts +457 -0
- package/skills/llm-wiki-skill/workbench/server/src/artifacts.ts +248 -0
- package/skills/llm-wiki-skill/workbench/server/src/auth.ts +164 -0
- package/skills/llm-wiki-skill/workbench/server/src/config.ts +130 -0
- package/skills/llm-wiki-skill/workbench/server/src/conversations.test.ts +159 -0
- package/skills/llm-wiki-skill/workbench/server/src/conversations.ts +270 -0
- package/skills/llm-wiki-skill/workbench/server/src/digest/batch.ts +189 -0
- package/skills/llm-wiki-skill/workbench/server/src/digest/concurrency.test.ts +36 -0
- package/skills/llm-wiki-skill/workbench/server/src/digest/concurrency.ts +31 -0
- package/skills/llm-wiki-skill/workbench/server/src/digest/subagent.ts +91 -0
- package/skills/llm-wiki-skill/workbench/server/src/extensions/artifacts.ts +81 -0
- package/skills/llm-wiki-skill/workbench/server/src/extensions/knowledge-base.ts +263 -0
- package/skills/llm-wiki-skill/workbench/server/src/extensions/new-wiki.ts +42 -0
- package/skills/llm-wiki-skill/workbench/server/src/extensions/synthesis.ts +172 -0
- package/skills/llm-wiki-skill/workbench/server/src/graph-watcher.test.ts +196 -0
- package/skills/llm-wiki-skill/workbench/server/src/graph.test.ts +113 -0
- package/skills/llm-wiki-skill/workbench/server/src/graph.ts +351 -0
- package/skills/llm-wiki-skill/workbench/server/src/index.ts +1148 -0
- package/skills/llm-wiki-skill/workbench/server/src/knowledge-bases.test.ts +30 -0
- package/skills/llm-wiki-skill/workbench/server/src/knowledge-bases.ts +321 -0
- package/skills/llm-wiki-skill/workbench/server/src/pages.test.ts +41 -0
- package/skills/llm-wiki-skill/workbench/server/src/pages.ts +160 -0
- package/skills/llm-wiki-skill/workbench/server/src/retrieval.test.ts +151 -0
- package/skills/llm-wiki-skill/workbench/server/src/retrieval.ts +427 -0
- package/skills/llm-wiki-skill/workbench/server/src/tool-status-events.test.ts +363 -0
- package/skills/llm-wiki-skill/workbench/server/src/tool-status-events.ts +616 -0
- package/skills/llm-wiki-skill/workbench/server/src/wiki-init.test.ts +19 -0
- package/skills/llm-wiki-skill/workbench/server/src/wiki-init.ts +188 -0
- package/skills/llm-wiki-skill/workbench/server/tsconfig.json +10 -0
- package/skills/llm-wiki-skill/workbench/tsconfig.json +20 -0
- package/skills/llm-wiki-skill/workbench/web/README.md +73 -0
- package/skills/llm-wiki-skill/workbench/web/components.json +21 -0
- package/skills/llm-wiki-skill/workbench/web/eslint.config.js +22 -0
- package/skills/llm-wiki-skill/workbench/web/index.html +16 -0
- package/skills/llm-wiki-skill/workbench/web/package.json +54 -0
- package/skills/llm-wiki-skill/workbench/web/src/App.tsx +1195 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/AddExternalDialog.tsx +375 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/AppearancePanel.tsx +158 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ArtifactView.tsx +15 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/BatchDigestPanel.tsx +117 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ChatPanel.tsx +890 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/CommandMenu.tsx +75 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ExportButtons.tsx +58 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/GraphPanel.tsx +800 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/GraphReader.tsx +52 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/GraphSelection.tsx +100 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/GraphSummaryDrawer.tsx +269 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/MainViewTabs.tsx +69 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/MarkdownView.tsx +106 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/NewWikiDialog.tsx +103 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/RefMenu.tsx +44 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/RightDrawer.tsx +298 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/SearchPanel.tsx +165 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/SettingsPanel.tsx +320 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/Sidebar.tsx +354 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ToolHistorySummary.tsx +111 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ToolStatusRunway.tsx +70 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/TopBar.tsx +348 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/renderers/DownloadOnlyRenderer.tsx +88 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/renderers/HtmlRenderer.tsx +92 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ui/button.tsx +52 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ui/command.tsx +50 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ui/dialog.tsx +156 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ui/input.tsx +21 -0
- package/skills/llm-wiki-skill/workbench/web/src/components/ui/tooltip.tsx +57 -0
- package/skills/llm-wiki-skill/workbench/web/src/index.css +4204 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/api.ts +648 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/appearance.ts +114 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/drawer-layout.ts +41 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/drawer-state.ts +168 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/graph-reader.ts +25 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/graph-selection-drawer.ts +35 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/graph-selection.ts +96 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/graph-summary-actions.ts +184 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/legacy-tool-status.ts +113 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/model-roles.ts +20 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/search-filter.ts +104 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/sse.ts +72 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/tool-status-format.ts +170 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/tool-status-model.ts +392 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/utils.ts +10 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/view-status.ts +16 -0
- package/skills/llm-wiki-skill/workbench/web/src/lib/wiki-links.ts +32 -0
- package/skills/llm-wiki-skill/workbench/web/src/main.tsx +10 -0
- package/skills/llm-wiki-skill/workbench/web/test/api.test.ts +61 -0
- package/skills/llm-wiki-skill/workbench/web/test/app-shell-drawer-layout.test.tsx +48 -0
- package/skills/llm-wiki-skill/workbench/web/test/appearance-panel.test.tsx +121 -0
- package/skills/llm-wiki-skill/workbench/web/test/appearance.test.ts +262 -0
- package/skills/llm-wiki-skill/workbench/web/test/chat-host-source.test.tsx +22 -0
- package/skills/llm-wiki-skill/workbench/web/test/chat-panel-auto-scroll.test.tsx +311 -0
- package/skills/llm-wiki-skill/workbench/web/test/chat-panel-bubbles.test.tsx +48 -0
- package/skills/llm-wiki-skill/workbench/web/test/chat-panel-composer.test.tsx +86 -0
- package/skills/llm-wiki-skill/workbench/web/test/chat-panel-tool-status.test.tsx +26 -0
- package/skills/llm-wiki-skill/workbench/web/test/export-batch-paper.test.tsx +101 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-drawer-state.test.ts +257 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-panel-paper.test.tsx +200 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-reader-request.test.ts +32 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-reader.test.ts +62 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-selection-drawer.test.ts +56 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-selection.test.ts +83 -0
- package/skills/llm-wiki-skill/workbench/web/test/graph-summary-actions.test.ts +188 -0
- package/skills/llm-wiki-skill/workbench/web/test/main-view-tabs.test.tsx +34 -0
- package/skills/llm-wiki-skill/workbench/web/test/markdown-view.test.tsx +34 -0
- package/skills/llm-wiki-skill/workbench/web/test/popup-menus.test.tsx +85 -0
- package/skills/llm-wiki-skill/workbench/web/test/render.test.tsx +30 -0
- package/skills/llm-wiki-skill/workbench/web/test/render.tsx +38 -0
- package/skills/llm-wiki-skill/workbench/web/test/right-drawer-graph-summary.test.tsx +287 -0
- package/skills/llm-wiki-skill/workbench/web/test/right-drawer-interactions.test.tsx +182 -0
- package/skills/llm-wiki-skill/workbench/web/test/search-filter.test.ts +65 -0
- package/skills/llm-wiki-skill/workbench/web/test/search-panel.test.tsx +155 -0
- package/skills/llm-wiki-skill/workbench/web/test/setup-dom.ts +66 -0
- package/skills/llm-wiki-skill/workbench/web/test/sidebar-v2-source.test.ts +17 -0
- package/skills/llm-wiki-skill/workbench/web/test/sidebar.test.tsx +110 -0
- package/skills/llm-wiki-skill/workbench/web/test/tool-history-summary.test.tsx +150 -0
- package/skills/llm-wiki-skill/workbench/web/test/tool-status-format.test.ts +107 -0
- package/skills/llm-wiki-skill/workbench/web/test/tool-status-model.test.ts +324 -0
- package/skills/llm-wiki-skill/workbench/web/test/tool-status-runway.test.ts +159 -0
- package/skills/llm-wiki-skill/workbench/web/test/topbar.test.tsx +248 -0
- package/skills/llm-wiki-skill/workbench/web/test/visual/paper-ui.ts +898 -0
- package/skills/llm-wiki-skill/workbench/web/test/wiki-links.test.ts +23 -0
- package/skills/llm-wiki-skill/workbench/web/test-results/paper-ui/actual/.gitkeep +1 -0
- package/skills/llm-wiki-skill/workbench/web/test-results/paper-ui/baseline/.gitkeep +1 -0
- package/skills/llm-wiki-skill/workbench/web/tsconfig.app.json +30 -0
- package/skills/llm-wiki-skill/workbench/web/tsconfig.json +7 -0
- package/skills/llm-wiki-skill/workbench/web/tsconfig.node.json +24 -0
- package/skills/llm-wiki-skill/workbench/web/vite.config.ts +28 -0
package/lib/roles/toolsets.js
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import { KanbanService } from '../domain/kanban-service.js';
|
|
3
|
+
import { WikiVaultClient } from '../wiki/wiki-vault-client.js';
|
|
4
|
+
import { isInsideKbRoot, ensureLocalKbRoot } from '../wiki/local-kb.js';
|
|
5
|
+
import { LocalWikiClient } from '../wiki/local-kb-client.js';
|
|
6
|
+
import { isStandaloneReviewNamespacePath } from '../domain/ocr-review.js';
|
|
7
|
+
import { isRoleComposed } from '../dispatcher/agent-runner.js';
|
|
8
|
+
import { ESCALATION_PARAM_KEYS } from './clean-fs-tools.js';
|
|
9
|
+
export { isRoleComposed };
|
|
3
10
|
import { buildKanbanTools } from '../tools/kanban-tools.js';
|
|
4
11
|
import { buildSpecCardTools } from '../tools/spec-card-tools.js';
|
|
5
12
|
import { buildWikiTools } from '../tools/wiki-tools.js';
|
|
6
13
|
import { buildPrefetchTools } from '../tools/prefetch-tools.js';
|
|
14
|
+
import { buildOcrReviewTool } from '../tools/ocr-review-tools.js';
|
|
7
15
|
import { WikiWorker } from './wiki-worker.js';
|
|
8
16
|
/** 直接写工具(无条件视为写能力;只读工具如 read/glob/grep 不算)。 */
|
|
9
17
|
const DIRECT_WRITE_TOOLS = new Set(['write', 'edit', 'rm', 'mv', 'cp', 'mkdir', 'mkfile']);
|
|
10
18
|
/** bash/run_code 命令中的写操作标记(写证据启发式;ls/cat/grep/git show 等只读不算)。
|
|
11
|
-
* 与 chain-auditor 同源;重定向标记用 \s>>?(要求 > 前有空白),避免 2>/dev/null 只读重定向误判。
|
|
12
|
-
|
|
19
|
+
* 与 chain-auditor 同源;重定向标记用 \s>>?(要求 > 前有空白),避免 2>/dev/null 只读重定向误判。
|
|
20
|
+
* git 细化(2026-09-08):merge(?!-base) 防 merge-base 查询被误判;tag 只认带非 -l/-n 参数的
|
|
21
|
+
* 变更形态(tag -l/-n/裸 为列表查询),两份正则(toolsets/chain-auditor)改动须同步。 */
|
|
22
|
+
const BASH_WRITE_RE = /(?:\b(?:touch|mkdir|rm|rmdir|mv|cp|tee|truncate|install|ln|dd|chmod|chown|make|cmake)\b|\bgit\s+(?:-C\s+\S+\s+)*(?:add|commit|push|mv|rm|checkout\s+-b|switch\s+-c|worktree\s+add|merge(?!-base)|rebase|reset|clean|restore|tag\s+(?!-l\b|-n\b)\S+|remote\s+add|apply)\b|\bpnpm\s+(?:add|install|remove|update|link)\b|\bnpm\s+(?:i|install|add|remove|uninstall|update)\b|\byarn\s+(?:add|remove)\b|\bbun\s+(?:add|install|remove)\b|\bsed\s+-i\b|\bperl\s+-i\b|\s>>?)/i;
|
|
13
23
|
/** run_code(JS/TS/Python 程序)中的写操作标记:文件写 API / 命令派发写工具。
|
|
14
|
-
* 含 Python 写标记(
|
|
24
|
+
* 含 Python 写标记(DT run_code 盲区闭环):open() 写模式精确版('w'/'a'/'w+'/'a+' 及
|
|
15
25
|
* wb/ab 等变体,读模式 'r' 不命中)、os. 模块写、pathlib Path 写、shutil 复制/移动/删除。 */
|
|
16
26
|
const CODE_WRITE_RE = /(?:\b(?:writeFileSync|writeFile|appendFileSync|appendFile|createWriteStream|unlinkSync|unlink|rmSync|rm|mkdirSync|mkdir|cpSync|renameSync)\b|\bwriteFile\(|\bfs\s*\.\s*(?:write|append|createWrite)|\bopen\(\s*['"][^'"\n]*['"]\s*,\s*(?:(?:mode|encoding|errors|buffering|newline|closefd|opener|text)\s*=\s*)?['"][wa][^'"\n]*['"]|\bos\s*\.\s*(?:remove|unlink|write|rmdir|makedirs|rename)\b|\.(?:write_text|write_bytes|unlink|mkdir|rename)\(|shutil\s*\.\s*(?:copy|move|rmtree))/i;
|
|
17
27
|
/** git 只读动词白名单:命中则 git 命令放行;其余 git 动词(含 checkout/branch/stash/merge/commit/push 等)一律拒绝。
|
|
@@ -25,7 +35,30 @@ const GIT_READ_VERBS = new Set(['status', 'log', 'show', 'diff', 'rev-parse', 'l
|
|
|
25
35
|
* 可直接执行任意文件写 API)∪ 原地编辑器 -i(sed -i / perl -i / awk -i inplace:可越过重定向直达
|
|
26
36
|
* 源码原地改写,P 写护栏硬约束须识别,与 BASH_WRITE_RE 同源)。 */
|
|
27
37
|
const GUARD_WRITE_INTENT_RE = /(?:\b(?:touch|mkdir|rm|rmdir|mv|cp|tee|truncate|install|ln|dd|chmod|chown|make|cmake)\b|\b(?:sed|perl|awk)\s+-i\b|\b(?:node|python|python3|perl|ruby|php|sh|bash)\s+-[ec]\b|(?<!2)>>|(?<!2)(?<!>)>)/i;
|
|
28
|
-
/**
|
|
38
|
+
/** run_code(JS/TS/Python 程序)重定向写意图:仅带空格形态 \s>>?(run_code 内嵌 shell 字符串的
|
|
39
|
+
* `echo x > f` 重定向,与 BASH_WRITE_RE 的带空格形态同源)。对 run_code 必须与 bash 的
|
|
40
|
+
* GUARD_WRITE_INTENT_RE 分离(planguard-falsepositive 根治):
|
|
41
|
+
* 1) 无空格 `>` 规则移除——JS 里 `=>`(箭头函数)、`remaining>0`(比较)是运算符而非重定向,
|
|
42
|
+
* 误判致 P 会话 openspec 裸 edit 随机被拒(15 次误报实证,2026-09-03);
|
|
43
|
+
* 2) GUARD 写动词(touch/mkdir/rm/…)与解释器 -c/-e、原地编辑器 -i 移除——真文件写由
|
|
44
|
+
* CODE_WRITE_RE 补回覆盖(writeFile/mkdir/unlink/open 写模式/os./pathlib/shutil),
|
|
45
|
+
* 内嵌 shell 裸动词由 CODE_SHELL_VERB_RE 补回覆盖,内嵌 shell 重定向由
|
|
46
|
+
* 本正则覆盖。三层分工与 accepted-risk 见 CODE_SHELL_VERB_RE 注释。 */
|
|
47
|
+
const CODE_REDIRECT_WRITE_RE = /\s>>?/;
|
|
48
|
+
/** run_code 内嵌 shell 裸动词写意图:CODE_WRITE_RE 只含文件写
|
|
49
|
+
* API,不含裸 shell 动词——run_code 字符串派发的 shell 命令(`child_process.exec('cp /tmp/x
|
|
50
|
+
* src/foo.ts')`)会绕过写护栏。词表对齐 GUARD_WRITE_INTENT_RE 动词清单中 CODE_WRITE_RE 未覆盖
|
|
51
|
+
* 的部分(rm/mkdir 已由 CODE_WRITE_RE 覆盖不重复;touch/rmdir/make/cmake 按评审定版不纳入)。
|
|
52
|
+
* word boundary 形态:JS 里作为独立词出现即拦(copy/cpSync/mkdirSync 等复合词不误伤),
|
|
53
|
+
* 误伤率与 GUARD 复用旧版一致可接受。三层分工:内嵌 shell 动词由本词表覆盖;重定向由
|
|
54
|
+
* CODE_REDIRECT_WRITE_RE(带空格 \s>>?)覆盖;JS/Python 文件写 API 由 CODE_WRITE_RE 覆盖。
|
|
55
|
+
* accepted-risk:内嵌 shell 无空格重定向(`exec('cat t>src/y')`)与 JS 运算符(=>、比较)
|
|
56
|
+
* 在正则上不可分辨——无空格 `>` 规则一旦保留即复活 planguard-falsepositive 运算符误报
|
|
57
|
+
* (15 次实证),GUARD 复用旧版拦得住它但误报面更大,取舍为放行(accepted-risk);
|
|
58
|
+
* run_code 带空格比较 `a > b` 且同 code 含 openspec/changes 路径时仍可能误拒(残余面小,
|
|
59
|
+
* 失败可恢复——模型改用 write 工具重试即可)。 */
|
|
60
|
+
const CODE_SHELL_VERB_RE = /\b(?:cp|mv|tee|dd|chmod|chown|ln|install|truncate)\b/i;
|
|
61
|
+
/** 剥去 shell 重定向目标 token 外壳的一层引号(' " `)(修复引号包裹 plan 路径的误拒)。
|
|
29
62
|
* 仅剥对称外壳一层;剥完仍走 resolve+isPlanPath,.. / 绝对路径逃逸不被削弱。 */
|
|
30
63
|
function stripShellQuotes(tok) {
|
|
31
64
|
const q = tok[0];
|
|
@@ -34,12 +67,13 @@ function stripShellQuotes(tok) {
|
|
|
34
67
|
}
|
|
35
68
|
return tok;
|
|
36
69
|
}
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
|
|
70
|
+
/** 从 bash/run_code 写意图命令提取实际写目标路径。
|
|
71
|
+
* redirectRe 按入口分流:bash 传 BASH_REDIRECT_TARGET_RE(无空格形态),run_code 传
|
|
72
|
+
* CODE_REDIRECT_TARGET_RE(带空格形态)——两形态各自命名,禁止共享开关参数。
|
|
73
|
+
* 另提取 writeFileSync(/appendFileSync( 首个字符串实参;提取不到返回空数组(调用方据此
|
|
74
|
+
* fail-closed 或放行)。 */
|
|
75
|
+
function extractWriteTargets(cmd, redirectRe) {
|
|
41
76
|
const out = [];
|
|
42
|
-
const redirectRe = /(?:(?<!2)>>|(?<!2)(?<!>)>)\s*([^\s;&|<>]+)/g;
|
|
43
77
|
let m;
|
|
44
78
|
while ((m = redirectRe.exec(cmd)) !== null) {
|
|
45
79
|
if (m[1])
|
|
@@ -50,27 +84,37 @@ function extractWriteTargets(cmd) {
|
|
|
50
84
|
if (m[2])
|
|
51
85
|
out.push(m[2]);
|
|
52
86
|
}
|
|
87
|
+
// 双模式:动词目标提取——必须捕获动词后【全部】路径实参(只取首个会让
|
|
88
|
+
// `mkdir -p <kb>/x /repo/y` 漏检第二个目标 → 护栏越权放行)。
|
|
89
|
+
// cp/mv/rm 的源+目标全部入列:任一在库根外即整体拒绝(fail-closed,accepted-risk:
|
|
90
|
+
// 库根内合法 cp/mv 改用 write 工具完成)。
|
|
91
|
+
const verbRe = /\b(?:touch|mkdir|tee|cp|mv|rm|install)\b([^;&|<>]*)/g;
|
|
92
|
+
while ((m = verbRe.exec(cmd)) !== null) {
|
|
93
|
+
for (const tok of m[1].split(/\s+/)) {
|
|
94
|
+
if (!tok || tok.startsWith('-'))
|
|
95
|
+
continue;
|
|
96
|
+
out.push(stripShellQuotes(tok));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
53
99
|
return out;
|
|
54
100
|
}
|
|
55
|
-
/**
|
|
101
|
+
/** bash 重定向目标提取(无空格形态):`>file`/`>>file` 是 bash 合法写重定向,必须识别为写目标;
|
|
102
|
+
* fd2 stderr 豁免沿用 lookbehind(重定向符前(首个 > 前)字符非 '2' 才算,2>/dev/null、2>&1、
|
|
103
|
+
* 2>>err.log 不命中),且禁止从 >> 的第二个 > 起匹配。仅用于 bash 入口。 */
|
|
104
|
+
const BASH_REDIRECT_TARGET_RE = /(?:(?<!2)>>|(?<!2)(?<!>)>)\s*([^\s;&|<>]+)/g;
|
|
105
|
+
/** run_code 重定向目标提取(带空格形态):run_code 是 JS/TS/Python 程序代码,无空格 `>` 是
|
|
106
|
+
* 运算符(箭头 =>、比较 remaining>0),旧版无空格形态会把 `>0` 的 "0" 提取成写目标 →
|
|
107
|
+
* isPlanPath("0")=false → openspec 裸 edit 随机误拒(15 次误报实证)。故只认带空格重定向
|
|
108
|
+
* (run_code 内嵌 shell 字符串 `echo x > /tmp/f`),与 CODE_REDIRECT_WRITE_RE 同源。 */
|
|
109
|
+
const CODE_REDIRECT_TARGET_RE = /\s>>?\s*([^\s;&|<>]+)/g;
|
|
110
|
+
/** 判定 wiki 路径是否位于 DT 评审命名空间 projects/<repoSlug>/<chainId>/review/
|
|
111
|
+
* (repoSlug=[a-z0-9-]+ 通配,chainId 精确匹配;拒绝 ../、绝对路径、跨链、旧格式直挂根)。 */
|
|
56
112
|
export function isReviewNamespacePath(pagePath, chainId) {
|
|
57
113
|
const p = String(pagePath ?? '');
|
|
58
114
|
if (!p || p.startsWith('/') || p.includes('..'))
|
|
59
115
|
return false;
|
|
60
|
-
const
|
|
61
|
-
return
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 评审引擎决策(DT):ocr(open-code-review Delegation 模式)优先;
|
|
65
|
-
* 不可用 fallback superpowers code-review;两者都不可用 → review-tool-unavailable(阻塞)。
|
|
66
|
-
* 纯函数便于单测;真实可用性探测在 agent-runner 装配(探活 ocr 二进制/失败)。
|
|
67
|
-
*/
|
|
68
|
-
export function resolveReviewEngine(available) {
|
|
69
|
-
if (available.ocr)
|
|
70
|
-
return 'ocr';
|
|
71
|
-
if (available.codeReview)
|
|
72
|
-
return 'code-review';
|
|
73
|
-
return 'review-tool-unavailable';
|
|
116
|
+
const chain = chainId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
117
|
+
return new RegExp(`^projects\\/[a-z0-9-]+\\/${chain}\\/review\\/`).test(p);
|
|
74
118
|
}
|
|
75
119
|
/**
|
|
76
120
|
* DT 写护栏 = PT 只读护栏(源码/git/写标记 bash 拒绝)+ wiki_write 仅 review namespace 收窄。
|
|
@@ -84,7 +128,7 @@ export function buildDTWriteGuard(repoRoot, chainId) {
|
|
|
84
128
|
const args = execution?.arguments ?? {};
|
|
85
129
|
const pagePath = String(args && typeof args === 'object' ? args['pagePath'] ?? '' : '');
|
|
86
130
|
if (!isReviewNamespacePath(pagePath, chainId))
|
|
87
|
-
return 'wiki-write-outside-review-namespace: DT may only write projects/<chain>/review/';
|
|
131
|
+
return 'wiki-write-outside-review-namespace: DT may only write projects/<repoSlug>/<chain>/review/';
|
|
88
132
|
}
|
|
89
133
|
return base(execution);
|
|
90
134
|
};
|
|
@@ -93,7 +137,7 @@ export function buildReadOnlyWriteGuard(_repoRoot) {
|
|
|
93
137
|
return (execution) => {
|
|
94
138
|
const name = String(execution?.name ?? '');
|
|
95
139
|
const args = execution?.arguments ?? {};
|
|
96
|
-
//
|
|
140
|
+
// 全名拦截——只读会话(W/PT/DT)fs 写无条件拒绝,不再依赖 repoRoot 子串 / hitsRepo。
|
|
97
141
|
// W 是 danger-full-access(无 workspace-write sandbox 兜底),可写 repo 外任意路径(~/x、/tmp/x、
|
|
98
142
|
// 其他项目源码),故必须工具级全名拦截封死。非写工具(read/glob/grep/wiki_* 等)照常放行。
|
|
99
143
|
if (DIRECT_WRITE_TOOLS.has(name))
|
|
@@ -102,31 +146,71 @@ export function buildReadOnlyWriteGuard(_repoRoot) {
|
|
|
102
146
|
const cmd = String(args && typeof args === 'object' ? (args['command'] ?? args['code'] ?? '') : '');
|
|
103
147
|
// bash 用 BASH_WRITE_RE(写动词 + git mutation + 带空格重定向)∪ GUARD_WRITE_INTENT_RE
|
|
104
148
|
// (无空格重定向 + 解释器 -c/-e)——全名拦截,写标记即拒,无论目标是否在 repo 内。
|
|
105
|
-
// run_code
|
|
106
|
-
|
|
107
|
-
|
|
149
|
+
// run_code 与 bash 分离(planguard-falsepositive 根治):CODE_WRITE_RE(文件写 API)
|
|
150
|
+
// ∪ CODE_SHELL_VERB_RE(内嵌 shell 裸动词,exec cp/mv 不再绕过)∪
|
|
151
|
+
// CODE_REDIRECT_WRITE_RE(带空格重定向)——无空格 > 在 JS 里是运算符(=>、比较),
|
|
152
|
+
// 不能复用 GUARD_WRITE_INTENT_RE(P 会话 15 次误报实证)。
|
|
153
|
+
const isWrite = name === 'run_code'
|
|
154
|
+
? CODE_WRITE_RE.test(cmd) || CODE_SHELL_VERB_RE.test(cmd) || CODE_REDIRECT_WRITE_RE.test(cmd)
|
|
155
|
+
: BASH_WRITE_RE.test(cmd) || GUARD_WRITE_INTENT_RE.test(cmd);
|
|
156
|
+
if (cmd && isWrite)
|
|
108
157
|
return 'write-to-repo-source-denied: ' + name + ' with write marker';
|
|
109
158
|
}
|
|
110
159
|
return undefined;
|
|
111
160
|
};
|
|
112
161
|
}
|
|
113
|
-
/**
|
|
162
|
+
/** 本地模式 KB 写护栏:全名只读拦截(base)之上,仅对「实际写目标全部为
|
|
163
|
+
* 库根内绝对路径」的写操作豁免。目标提取不到 / 相对路径 / 越界 → 维持 base 拒绝(fail-closed)。
|
|
164
|
+
* 仅 local 模式对 W/DT 装配;remote 模式仍用 buildReadOnlyWriteGuard(库根写也被拒)。
|
|
165
|
+
* 审查修订:extractWriteTargets 保持既有双参签名(cmd, redirectRe),按入口分流
|
|
166
|
+
* 传 BASH_REDIRECT_TARGET_RE / CODE_REDIRECT_TARGET_RE(与 buildPlanWriteGuard 同款)——
|
|
167
|
+
* 单参调用会在首个写意图命令上 TypeError。 */
|
|
168
|
+
export function buildKbWriteGuard(kbRoot) {
|
|
169
|
+
const base = buildReadOnlyWriteGuard(kbRoot);
|
|
170
|
+
const isKbTarget = (t) => isInsideKbRoot(kbRoot, t);
|
|
171
|
+
return (execution) => {
|
|
172
|
+
const baseReason = base(execution);
|
|
173
|
+
if (!baseReason)
|
|
174
|
+
return undefined;
|
|
175
|
+
const name = String(execution?.name ?? '');
|
|
176
|
+
const args = execution?.arguments ?? {};
|
|
177
|
+
const a = args && typeof args === 'object' ? args : {};
|
|
178
|
+
if (DIRECT_WRITE_TOOLS.has(name)) {
|
|
179
|
+
const target = String(a['path'] ?? a['file_path'] ?? '');
|
|
180
|
+
if (target && isKbTarget(target))
|
|
181
|
+
return undefined;
|
|
182
|
+
return baseReason;
|
|
183
|
+
}
|
|
184
|
+
if (name === 'bash' || name === 'run_code') {
|
|
185
|
+
const cmd = String(a['command'] ?? a['code'] ?? '');
|
|
186
|
+
if (!cmd)
|
|
187
|
+
return baseReason;
|
|
188
|
+
// 双参签名 + 按入口分流 redirect 正则(审查修订);targets 为空 = 写意图但提取不到目标 → fail-closed 拒绝
|
|
189
|
+
const targets = extractWriteTargets(cmd, name === 'bash' ? BASH_REDIRECT_TARGET_RE : CODE_REDIRECT_TARGET_RE);
|
|
190
|
+
if (targets.length > 0 && targets.every(isKbTarget))
|
|
191
|
+
return undefined;
|
|
192
|
+
return baseReason;
|
|
193
|
+
}
|
|
194
|
+
return baseReason;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
/** P 专用写护栏:读全放行;git mutation 一律拒绝;写仅允许目标仓库 openspec/changes 目录。
|
|
114
198
|
* 直接 fs 写工具 → 路径经 resolve 归一化后须落在 <workspaceRoot>/openspec/changes/ 之下(相邻段对判定);
|
|
115
199
|
* bash/run_code 写标记命令 → 命令文本须含 `openspec/changes` 子串,且提取出的实际写目标(重定向
|
|
116
|
-
* 目标 / writeFileSync 实参)逐条经 resolve+isPlanPath
|
|
200
|
+
* 目标 / writeFileSync 实参)逐条经 resolve+isPlanPath 校验(杀 openspec/changes/../.. 穿越写源码)。
|
|
117
201
|
* 源码/src/lib/tests 等写不入(不含该子串)——"禁止改动源码"为工具级硬约束,非 prompt 软约束。
|
|
118
202
|
* execution 以 dsh-tools 形态 { name, arguments } 传入(与 buildReadOnlyWriteGuard 一致)。 */
|
|
119
203
|
export function buildPlanWriteGuard(workspaceRoot) {
|
|
120
204
|
const wsRoot = workspaceRoot.replace(/\/+$/, '');
|
|
121
205
|
/** 目标路径须解析后落在 wsRoot 之下、且含相邻 openspec→changes 段对。
|
|
122
|
-
* resolve 折叠 ../ 与重复斜杠(杀
|
|
123
|
-
* 相对路径(openspec/changes/x.md)经 resolve 归到 wsRoot 之下 →
|
|
206
|
+
* resolve 折叠 ../ 与重复斜杠(杀 .. 穿越);wsRoot + '/' 边界前缀(杀 /ws/main2 前缀逃逸);
|
|
207
|
+
* 相对路径(openspec/changes/x.md)经 resolve 归到 wsRoot 之下 → 允许。 */
|
|
124
208
|
const isPlanPath = (p) => {
|
|
125
209
|
if (!p)
|
|
126
210
|
return false;
|
|
127
211
|
const resolved = resolve(wsRoot, p);
|
|
128
212
|
// POSIX 上 \ 是合法文件名字符(如目录名 openspec\changes),反斜杠归一化仅 win32 需要,
|
|
129
|
-
// 否则会把它折叠成相邻 openspec→changes
|
|
213
|
+
// 否则会把它折叠成相邻 openspec→changes 段对而被误放行。
|
|
130
214
|
const norm = process.platform === 'win32' ? resolved.replace(/\\/g, '/') : resolved;
|
|
131
215
|
if (!norm.startsWith(wsRoot + '/'))
|
|
132
216
|
return false;
|
|
@@ -140,6 +224,14 @@ export function buildPlanWriteGuard(workspaceRoot) {
|
|
|
140
224
|
const args = execution?.arguments ?? {};
|
|
141
225
|
const a = args && typeof args === 'object' ? args : {};
|
|
142
226
|
if (DIRECT_WRITE_TOOLS.has(name)) {
|
|
227
|
+
// Fix(2026-09-02 P 会话 30 连败事故):P 会话为 danger-full-access(天花板),官方 write/edit
|
|
228
|
+
// schema 仍广播可选参数 sandbox_permissions,模型误填后任何值都触发官方 approveEscalation
|
|
229
|
+
// "not strictly wider" 拒绝(escalation 必须严格更宽,天花板无更宽可升)。此处工具级拦截:
|
|
230
|
+
// 带该参数即拒并返回自解释文案(模型一轮纠偏改用裸 file_path+content),先于路径判定(参数
|
|
231
|
+
// 本身即非法,与目标无关)。
|
|
232
|
+
if (a['sandbox_permissions'] !== undefined) {
|
|
233
|
+
return 'plan-guard: 本会话已是 danger-full-access(权限天花板),禁止附带 sandbox_permissions(任何值都会被拒绝,且无需升级)。请直接用 file_path + content 裸写 openspec/changes/ 下的目标文件,不要重试被拒的带参调用。';
|
|
234
|
+
}
|
|
143
235
|
const target = String(a['path'] ?? a['file_path'] ?? '');
|
|
144
236
|
if (isPlanPath(target))
|
|
145
237
|
return undefined;
|
|
@@ -149,11 +241,11 @@ export function buildPlanWriteGuard(workspaceRoot) {
|
|
|
149
241
|
const cmd = String(a['command'] ?? a['code'] ?? '');
|
|
150
242
|
if (!cmd)
|
|
151
243
|
return undefined;
|
|
152
|
-
// FIRST git
|
|
244
|
+
// FIRST git 判定(仅命令文本,不扫写入内容——修复内容误拒):
|
|
153
245
|
// 按 && / || / ; / | / 换行 分段,逐段提取首个 git 动词(先跳过 git 全局选项
|
|
154
246
|
// --no-pager/-p/-v/--bare/--literal-pathspecs/--no-replace-objects/-C <path>/-c <kv>/
|
|
155
247
|
// --git-dir=/--work-tree=/--namespace=)。任何一段含 git 却提取不到动词(如 git --version
|
|
156
|
-
// 或裸 git)→ fail-closed 拒绝;动词非只读白名单 →
|
|
248
|
+
// 或裸 git)→ fail-closed 拒绝;动词非只读白名单 → 拒绝。修复链式绕过与全局选项前缀 fall-through。
|
|
157
249
|
const segments = cmd.split(/\s*(?:&&|\|\||;|\||\n)\s*/);
|
|
158
250
|
for (const seg of segments) {
|
|
159
251
|
if (!/\bgit\b/.test(seg))
|
|
@@ -163,19 +255,23 @@ export function buildPlanWriteGuard(workspaceRoot) {
|
|
|
163
255
|
if (!verb || !GIT_READ_VERBS.has(verb))
|
|
164
256
|
return 'plan-guard: P 禁止 git 操作';
|
|
165
257
|
}
|
|
166
|
-
// THEN
|
|
167
|
-
// run_code
|
|
168
|
-
//
|
|
258
|
+
// THEN 写意图:bash 用增强写标记(含无空格重定向与解释器 -c/-e)且不含 plan 路径 → 拒绝。
|
|
259
|
+
// run_code 与 bash 分离(planguard-falsepositive 根治,2026-09-03):CODE_WRITE_RE(文件
|
|
260
|
+
// 写 API)∪ CODE_SHELL_VERB_RE(内嵌 shell 裸动词)∪ CODE_REDIRECT_WRITE_RE
|
|
261
|
+
// (带空格重定向)——无空格 > 在 JS 里是运算符(=>、比较 remaining>0),
|
|
262
|
+
// GUARD_WRITE_INTENT_RE 复用致 openspec 裸 edit 随机误拒(15 次实证);GUARD 动词/
|
|
263
|
+
// 解释器对 run_code 移除的论证见 CODE_REDIRECT_WRITE_RE / CODE_SHELL_VERB_RE 注释。
|
|
169
264
|
const isWrite = name === 'run_code'
|
|
170
|
-
? CODE_WRITE_RE.test(cmd) ||
|
|
265
|
+
? CODE_WRITE_RE.test(cmd) || CODE_SHELL_VERB_RE.test(cmd) || CODE_REDIRECT_WRITE_RE.test(cmd)
|
|
171
266
|
: GUARD_WRITE_INTENT_RE.test(cmd);
|
|
172
267
|
if (isWrite) {
|
|
173
268
|
if (!isPlanCmd(cmd))
|
|
174
269
|
return 'plan-guard: P 写仅允许 openspec/changes/ 目录(禁止改动源码)';
|
|
175
|
-
//
|
|
176
|
-
// 首个字符串实参,逐条 resolve + isPlanPath(与 write/edit
|
|
270
|
+
// 含 plan 标记仍须验证实际写目标——重定向 >/>> 目标与 writeFileSync(/appendFileSync(
|
|
271
|
+
// 首个字符串实参,逐条 resolve + isPlanPath(与 write/edit 入口同款判定,杀同款
|
|
177
272
|
// openspec/changes/../.. 穿越写源码,补齐 bash/run_code 入口)。任一条目标不通过 → 拒绝。
|
|
178
|
-
|
|
273
|
+
// 重定向形态按入口分流:bash 无空格(>f 合法写),run_code 带空格(无空格 > 是运算符)。
|
|
274
|
+
const targets = extractWriteTargets(cmd, name === 'run_code' ? CODE_REDIRECT_TARGET_RE : BASH_REDIRECT_TARGET_RE);
|
|
179
275
|
if (targets.length === 0) {
|
|
180
276
|
// 快速防线:命令同时含 openspec/changes 与 .. 但目标解析不出(无法提取)→ fail-closed 拒绝
|
|
181
277
|
if (cmd.includes('..'))
|
|
@@ -191,43 +287,72 @@ export function buildPlanWriteGuard(workspaceRoot) {
|
|
|
191
287
|
return undefined;
|
|
192
288
|
};
|
|
193
289
|
}
|
|
194
|
-
/**
|
|
195
|
-
*
|
|
290
|
+
/** 工具注册表解析:直取 ctx.tools(官方语义),失败回退 ctx.get('tools')(cordis 服务路径,
|
|
291
|
+
* 与 v-orchestrator setup 取 agentPresets 同款)。宿主/ cordis 版本混装(web profile 实证
|
|
292
|
+
* 0.1.1-rc.2 包 + 4.0.1/4.0.2 peer 并存)下直取路径可能静默 undefined(旧语义),回退路径
|
|
293
|
+
* 保证角色工具面仍能注册。两者皆空时必须告警——静默跳过=角色裸奔且无痕。 */
|
|
294
|
+
function resolveToolRegistry(agentCtx) {
|
|
295
|
+
const direct = agentCtx.tools;
|
|
296
|
+
if (direct && typeof direct.register === 'function')
|
|
297
|
+
return direct;
|
|
298
|
+
const fallback = agentCtx.get?.('tools');
|
|
299
|
+
if (fallback && typeof fallback.register === 'function') {
|
|
300
|
+
console.error('[dsh-swarm][debug] tool registry via ctx.get fallback (direct .tools missing)');
|
|
301
|
+
return fallback;
|
|
302
|
+
}
|
|
303
|
+
return undefined;
|
|
304
|
+
}
|
|
305
|
+
function safeKeys(ctx) {
|
|
306
|
+
try {
|
|
307
|
+
return Object.keys(ctx).slice(0, 12).join(',');
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return '<unkeyed>';
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/** 按角色在 agent scope 注册工具面(统一注册策略):
|
|
314
|
+
* 所有 kanban 工具从工具工厂选取 + getCaller 闭包(actor=role、boundTaskId=taskId)。
|
|
196
315
|
* can() 权限兜底仍保留在工具 execute 内(纵深防御第二道)。 */
|
|
197
316
|
export async function installRoleTools(agentCtx, role, deps) {
|
|
317
|
+
const kbMode = deps.kbMode ?? 'remote';
|
|
198
318
|
console.error('[dsh-swarm][debug] installRoleTools role=' + role + ' task=' + deps.taskId);
|
|
199
319
|
const caller = () => ({ actor: role, boundTaskId: deps.taskId });
|
|
200
320
|
const allKanban = buildKanbanTools(deps.kanban, caller);
|
|
201
321
|
// 每角色可用的 kanban 工具名(V 额外编排、P/W/D 任务工具)
|
|
202
|
-
//
|
|
322
|
+
// 设计表另有 V 专属 kanban_link/chain_show,src/tools/kanban-tools.ts 未实现这两项,
|
|
203
323
|
// 故保持不注册(不为实现而实现多余工具),与设计表的差异以此注释声明。
|
|
204
324
|
const namesFor = {
|
|
205
325
|
v: ['kanban_create', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment', 'kanban_show', 'kanban_chain', 'kanban_list'],
|
|
206
326
|
p: ['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment'],
|
|
207
327
|
w: ['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment'],
|
|
208
328
|
d: ['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment'],
|
|
209
|
-
//
|
|
329
|
+
// 评审角色(正式装配工具面):PT/DT 任务工具 + 只读(spec 视图等)
|
|
210
330
|
pt: ['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment'],
|
|
211
331
|
dt: ['kanban_show', 'kanban_chain', 'kanban_list', 'kanban_complete', 'kanban_block', 'kanban_heartbeat', 'kanban_comment'],
|
|
212
332
|
};
|
|
213
333
|
const want = new Set(namesFor[role]);
|
|
214
|
-
const registry = agentCtx
|
|
215
|
-
if (!registry)
|
|
216
|
-
|
|
334
|
+
const registry = resolveToolRegistry(agentCtx);
|
|
335
|
+
if (!registry) {
|
|
336
|
+
console.error('[dsh-swarm][error] tool registry unavailable — role tools NOT registered (silent capability loss risk) role=' + role + ' task=' + (deps.taskId ?? '-') + ' ctxKeys=' + safeKeys(agentCtx));
|
|
337
|
+
return; // 保持返回不抛:本轮先取证,全角色 fail-fast 另行决策
|
|
338
|
+
}
|
|
217
339
|
for (const tool of allKanban) {
|
|
218
340
|
const name = tool.name;
|
|
219
341
|
if (name && want.has(name))
|
|
220
342
|
registry.register(tool);
|
|
221
343
|
}
|
|
222
344
|
if (role === 'w') {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
345
|
+
if (kbMode === 'remote') {
|
|
346
|
+
for (const tool of buildWikiTools(deps.wiki, caller))
|
|
347
|
+
registry.register(tool);
|
|
348
|
+
}
|
|
349
|
+
// local:wiki 三原语不注册,W 经 skill 工具(preset 提供)自治查写;prefetch/spec 视图保留
|
|
350
|
+
// 设计表:W 对规格卡只读(spec_card_view)
|
|
226
351
|
for (const tool of buildSpecCardTools(deps.kanban, caller)) {
|
|
227
352
|
if (tool.name === 'spec_card_view')
|
|
228
353
|
registry.register(tool);
|
|
229
354
|
}
|
|
230
|
-
const worker = new WikiWorker(deps.kanban, deps.wiki, { pagePrefix: 'projects/' });
|
|
355
|
+
const worker = new WikiWorker(deps.kanban, deps.wiki, { pagePrefix: 'projects/', kbMode: deps.kbMode });
|
|
231
356
|
const getTask = async (taskId) => {
|
|
232
357
|
const state = await deps.kanban.snapshot();
|
|
233
358
|
const t = state.tasks.get(taskId);
|
|
@@ -240,10 +365,12 @@ export async function installRoleTools(agentCtx, role, deps) {
|
|
|
240
365
|
}
|
|
241
366
|
else if (role === 'd') {
|
|
242
367
|
// D:只读 KB——注册 wiki_read + wiki_search(均走 can('wiki-read')=w/d 只读兜底);规格卡只读
|
|
243
|
-
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
368
|
+
if (kbMode === 'remote') {
|
|
369
|
+
for (const tool of buildWikiTools(deps.wiki, caller)) {
|
|
370
|
+
const name = tool.name;
|
|
371
|
+
if (name === 'wiki_read' || name === 'wiki_search')
|
|
372
|
+
registry.register(tool);
|
|
373
|
+
}
|
|
247
374
|
}
|
|
248
375
|
for (const tool of buildSpecCardTools(deps.kanban, caller)) {
|
|
249
376
|
if (tool.name === 'spec_card_view')
|
|
@@ -265,16 +392,20 @@ export async function installRoleTools(agentCtx, role, deps) {
|
|
|
265
392
|
}
|
|
266
393
|
}
|
|
267
394
|
else if (role === 'dt') {
|
|
268
|
-
// DT:只读评审——spec_card_view + wiki 只读(评审区写由 ToolGuard
|
|
395
|
+
// DT:只读评审——spec_card_view + wiki 只读(评审区写由 ToolGuard 收窄)
|
|
269
396
|
for (const tool of buildSpecCardTools(deps.kanban, caller)) {
|
|
270
397
|
if (tool.name === 'spec_card_view')
|
|
271
398
|
registry.register(tool);
|
|
272
399
|
}
|
|
273
|
-
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
400
|
+
if (kbMode === 'remote') {
|
|
401
|
+
for (const tool of buildWikiTools(deps.wiki, caller)) {
|
|
402
|
+
const n = tool.name;
|
|
403
|
+
if (n === 'wiki_read' || n === 'wiki_search' || n === 'wiki_write')
|
|
404
|
+
registry.register(tool);
|
|
405
|
+
}
|
|
277
406
|
}
|
|
407
|
+
// ocr_review:ocr CLI 三子命令(preview/rule/managed);未安装/托管未配置在 execute 内降级引导,注册无条件
|
|
408
|
+
registry.register(buildOcrReviewTool({ cwd: () => process.cwd() }));
|
|
278
409
|
}
|
|
279
410
|
else if (role === 'v') {
|
|
280
411
|
for (const tool of buildSpecCardTools(deps.kanban, caller)) {
|
|
@@ -283,11 +414,11 @@ export async function installRoleTools(agentCtx, role, deps) {
|
|
|
283
414
|
}
|
|
284
415
|
}
|
|
285
416
|
}
|
|
286
|
-
// ── 0.1.0 delegation
|
|
287
|
-
//
|
|
288
|
-
// scoped
|
|
417
|
+
// ── 0.1.0 delegation:全局子代理写护栏────────────────────────────
|
|
418
|
+
// 框架事实:agent.ctx guard 不被子代理继承;toolFilter 对 preset
|
|
419
|
+
// scoped 工具零作用。故 DT 子代理只读防线只能在插件全局 ctx 注册 guard(全局
|
|
289
420
|
// 生效),按发起 agent 会话 header 的 agentPreset 精准判定(childSessionMeta 在子代理
|
|
290
|
-
// join 父组合时记录 preset id
|
|
421
|
+
// join 父组合时记录 preset id):仅 kanban-dt 系收紧,其余(kanban-d 系、主会话
|
|
291
422
|
// 及其子代理)一律放行。
|
|
292
423
|
/** DT 任务运行期 taskId → chainId 同步缓存(guard 内 wiki review namespace 校验的
|
|
293
424
|
* 解析源;AgentRunner 在 DT 任务 runTask 生命周期内维护,与 permissionBlockedTasks
|
|
@@ -319,7 +450,7 @@ export function buildSubagentTreeGuard(deps = {}) {
|
|
|
319
450
|
return undefined;
|
|
320
451
|
// 仅真实子代理(parentSession 为 kbn- 前缀)受全局护栏约束;DT 父会话自身
|
|
321
452
|
// parentSession 是主会话或缺失(非 kbn- 前缀),chainId 解析不到 → 空,若误拦
|
|
322
|
-
// 会把 DT 评审写入(wiki_write projects/<chain>/review/...)拒掉 → 直接放行。
|
|
453
|
+
// 会把 DT 评审写入(wiki_write projects/<repoSlug>/<chain>/review/...)拒掉 → 直接放行。
|
|
323
454
|
const parent = header.parentSession;
|
|
324
455
|
if (typeof parent !== 'string' || !parent.startsWith('kbn-'))
|
|
325
456
|
return undefined;
|
|
@@ -330,3 +461,222 @@ export function buildSubagentTreeGuard(deps = {}) {
|
|
|
330
461
|
return buildDTWriteGuard(repoRoot, chainId)(execution);
|
|
331
462
|
};
|
|
332
463
|
}
|
|
464
|
+
/** 蜂群模式主会话硬闸:全局 guard,按 header.agentPreset==='swarm'
|
|
465
|
+
* 精准判定(先例 buildSubagentTreeGuard)。swarm 会话 = 扩权参数教学拦截(宿主 bash/write/edit
|
|
466
|
+
* schema 广播 sandbox_permissions/justification,模型带参重试会触发天花板会话 approveEscalation
|
|
467
|
+
* 死循环——独立 DT 同款拦截)+ git 反选(与独立 DT 共用 GIT_MUTATION_VERBS/dualVerbGitDenyReason,
|
|
468
|
+
* buildPlanWriteGuard 同款分段提取判定,跳过 git 全局选项、提取不到动词 fail-closed,先行判定——
|
|
469
|
+
* git 变更动词多数同时命中只读基座的写标记,须以 swarm-guard 文案优先返回)+ 只读基座
|
|
470
|
+
* (buildReadOnlyWriteGuard:直接写工具全名拦截 + bash/run_code 写标记)。其余会话恒放行
|
|
471
|
+
* (角色会话自有 agent scope 护栏兜底,双保险不叠加)。 */
|
|
472
|
+
export function buildSwarmSessionGuard() {
|
|
473
|
+
return (execution) => {
|
|
474
|
+
const header = extractSessionHeader(execution?.agent);
|
|
475
|
+
if (!header || header.agentPreset !== 'swarm')
|
|
476
|
+
return undefined;
|
|
477
|
+
const name = String(execution?.name ?? '');
|
|
478
|
+
const args = execution?.arguments ?? {};
|
|
479
|
+
if (name === 'bash' || name === 'run_code' || name === 'write' || name === 'edit') {
|
|
480
|
+
// 扩权参数教学拦截:swarm 直聊会话是 danger-full-access 天花板(无更宽可升),
|
|
481
|
+
// 模型带参会被宿主 approveEscalation 拒(2026-09-02 P 会话 30 连败同根;swarm 会话
|
|
482
|
+
// 宿主直建、无 agent-runner setup 钩子装不了剥参 shadow,guard 拦截是唯一硬面)。
|
|
483
|
+
if (args && typeof args === 'object' && ESCALATION_PARAM_KEYS.some((k) => args[k] !== undefined)) {
|
|
484
|
+
return 'swarm-guard: 本会话为只读蜂群会话——不要传 sandbox_permissions/justification 扩权参数(天花板会话无可升级权限,带参必被宿主拒绝);去掉该参数后重试';
|
|
485
|
+
}
|
|
486
|
+
if (name === 'bash' || name === 'run_code') {
|
|
487
|
+
const cmd = String(args && typeof args === 'object' ? (args['command'] ?? args['code'] ?? '') : '');
|
|
488
|
+
if (cmd) {
|
|
489
|
+
const segments = cmd.split(/\s*(?:&&|\|\||;|\||\n)\s*/);
|
|
490
|
+
for (const seg of segments) {
|
|
491
|
+
if (!/\bgit\b/.test(seg))
|
|
492
|
+
continue;
|
|
493
|
+
const m = seg.match(GIT_VERB_RE);
|
|
494
|
+
const verb = m?.[1];
|
|
495
|
+
// 反选:仅禁变更动词与双态动词的变更子形态;提取不到动词 fail-closed 拒
|
|
496
|
+
if (!verb || GIT_MUTATION_VERBS.has(verb))
|
|
497
|
+
return SWARM_GIT_DENY;
|
|
498
|
+
const sub = dualVerbGitDenyReason(verb, seg.slice((m.index ?? 0) + m[0].length), SWARM_GIT_DENY);
|
|
499
|
+
if (sub)
|
|
500
|
+
return sub;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
const baseReason = buildReadOnlyWriteGuard(header.cwd || '/')(execution);
|
|
506
|
+
if (baseReason)
|
|
507
|
+
return baseReason;
|
|
508
|
+
return undefined;
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
// ── 独立评审(standalone DT):全局 guard + 评审工具全局注册 ───────────────
|
|
512
|
+
// 独立评审 = 用户在 dsh web 以「交付评审官 (DT)」preset 直接对话:无绑定任务、不经
|
|
513
|
+
// agent-runner 角色组合(无角色工具面、无 agent-scope guard)。本节在插件全局 ctx
|
|
514
|
+
// 注册 buildStandaloneDtGuard(仅对独立 DT 会话收紧)与 registerStandaloneReviewerTools
|
|
515
|
+
// (ocr_review + wiki 三原语);链上组合 DT 会话不受影响(自有 agent-scope guard 兜底)。
|
|
516
|
+
/** 只读评审类会话(独立 DT / 蜂群主会话共用)禁用的 git 变更动词(反选:只枚举变更面,其余动词放行)。
|
|
517
|
+
* 决策(2026-09-08):查询/clone/fetch/裸 checkout·switch 放开,仅禁改动代码与分支状态的
|
|
518
|
+
* git 操作;双态动词(checkout/switch/branch/tag/stash/remote/worktree/config/reflog/notes)
|
|
519
|
+
* 的变更子形态由 dualVerbGitDenyReason 单独判定,此处只列整词禁用项。 */
|
|
520
|
+
const GIT_MUTATION_VERBS = new Set([
|
|
521
|
+
'push', 'merge', 'rebase', 'revert', 'cherry-pick', 'filter-branch', 'filter-repo', 'replace',
|
|
522
|
+
'reset', 'restore', 'clean', 'commit', 'add', 'am', 'apply', 'mv', 'rm',
|
|
523
|
+
'gc', 'prune', 'repack', 'bisect',
|
|
524
|
+
]);
|
|
525
|
+
/** 独立评审 git 变更拒绝文案(错误文案即模型的 prompt:写明放开面,教模型改用合法形态)。 */
|
|
526
|
+
const STANDALONE_GIT_DENY = 'standalone-dt: 独立评审禁止 git 变更操作(push/merge/rebase/reset/commit 等);查询、clone/fetch 与 checkout/switch 裸切换放行';
|
|
527
|
+
/** 蜂群会话 git 变更拒绝文案(同款反选语义;文案点名 swarm-guard 便于测试与日志归因)。 */
|
|
528
|
+
const SWARM_GIT_DENY = 'swarm-guard: 蜂群会话禁止 git 变更操作(push/merge/rebase/reset/commit 等,执行由工作流 D 角色完成);查询与 clone/fetch 放行';
|
|
529
|
+
/** git 动词提取:跳过全局选项(与 swarm-guard 同款);提取不到动词 fail-closed 拒。 */
|
|
530
|
+
const GIT_VERB_RE = /\bgit(?:\s+(?:--no-pager|-p|-v|--bare|--literal-pathspecs|--no-replace-objects|-C\s+\S+|-c\s+\S+|--git-dir=\S+|--work-tree=\S+|--namespace=\S+))*\s+([a-zA-Z][\w-]*)/;
|
|
531
|
+
/** 双态 git 动词的变更子形态判定(rest = 动词之后的命令原文,deny = 命中时的拒绝文案)。
|
|
532
|
+
* 只认旗标语义不做路径解析;`checkout <path>` 与裸切分支同形(无 `--` 分隔)按放行处理
|
|
533
|
+
* (评审常在临时 clone 中进行,残留风险可接受)。undefined = 放行。 */
|
|
534
|
+
function dualVerbGitDenyReason(verb, rest, deny) {
|
|
535
|
+
switch (verb) {
|
|
536
|
+
case 'checkout': // 建分支(-b/-B/--orphan)与 `-- <path>` 丢弃工作区改动拒;裸切换放行
|
|
537
|
+
if (/^\s+(?:-\S+\s+)*(?:-b|-B|--orphan)\b/.test(rest))
|
|
538
|
+
return deny;
|
|
539
|
+
if (/^\s+--(?:\s|$)/.test(rest))
|
|
540
|
+
return deny;
|
|
541
|
+
return undefined;
|
|
542
|
+
case 'switch': // 建/替换分支拒;裸切换放行
|
|
543
|
+
return /^\s+(?:-\S+\s+)*(?:-c|-C|--create|--orphan)\b/.test(rest) ? deny : undefined;
|
|
544
|
+
case 'branch': { // 仅裸/任意非管理旗标放行;建删改(管理旗标 -m/-M/-c/-C/-d/-D 或位置参数命名)拒
|
|
545
|
+
const flagsOnly = /^(?:\s+-\S+)*\s*$/.test(rest);
|
|
546
|
+
const mgmt = /\s-(?:m|M|c|C|d|D)\b/.test(rest);
|
|
547
|
+
return !mgmt && flagsOnly ? undefined : deny;
|
|
548
|
+
}
|
|
549
|
+
case 'tag': // 仅裸/-l/-n 列表放行
|
|
550
|
+
return /^\s*$|^\s+(?:-l\b|-n\b)/.test(rest) ? undefined : deny;
|
|
551
|
+
case 'stash': // 仅 list/show/find 放行(裸 = 打印帮助)
|
|
552
|
+
return /^\s*$|^\s+(?:list|show|find)\b/.test(rest) ? undefined : deny;
|
|
553
|
+
case 'remote': // 仅裸/-v/--verbose/get-url 放行
|
|
554
|
+
return /^\s*$|^\s+(?:-v\b|--verbose\b)|^\s+get-url\b/.test(rest) ? undefined : deny;
|
|
555
|
+
case 'worktree': // 仅裸/list 放行
|
|
556
|
+
return /^\s*$|^\s+list\b/.test(rest) ? undefined : deny;
|
|
557
|
+
case 'config': // 仅读旗标放行;单/双位置参数写入(含 --global)与 --unset 一律拒
|
|
558
|
+
return /^\s*$|^\s+(?:--get\b|--get-all\b|--get-regexp\b|--list\b|-l\b)/.test(rest) ? undefined : deny;
|
|
559
|
+
case 'reflog': // 仅 delete/expire 拒,其余(裸/show)放行
|
|
560
|
+
return /^\s+(?:delete|expire)\b/.test(rest) ? deny : undefined;
|
|
561
|
+
case 'notes': // 仅裸/list/show 放行
|
|
562
|
+
return /^\s*$|^\s+(?:list|show)\b/.test(rest) ? undefined : deny;
|
|
563
|
+
default:
|
|
564
|
+
return undefined;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/** 独立评审(standalone DT)全局硬闸。独立会话判定(同时成立):
|
|
568
|
+
* header.agentPreset === 'kanban-dt'、未经角色组合标记(!isRoleComposed)、parentSession
|
|
569
|
+
* 非 kbn- 前缀(与 buildSubagentTreeGuard 判据对齐:有 kbn- parentSession 的是链上系
|
|
570
|
+
* DT 子代理,交由该 guard 管——其 incarnation 可能无组合标记、宿主 id 也可能非 kbn-
|
|
571
|
+
* 前缀,漏判会把链评审写入误当独立模式拒掉)、且(能从 execution.agent 取到 session
|
|
572
|
+
* id 时)id 非 kbn- 前缀。不满足 → 不走独立规则。
|
|
573
|
+
* 独立模式规则(按序):
|
|
574
|
+
* 1. kanban 写工具(complete/block/comment/heartbeat/create)→ 拒(独立评审不挂任务链);
|
|
575
|
+
* 2. bash/run_code/write/edit → 扩权参数教学拦截(sandbox_permissions/justification 任一
|
|
576
|
+
* 出现即拒并教模型去参——只读会话无扩权场景,宿主沙箱校验报错文案晦涩);bash/run_code
|
|
577
|
+
* 再过 git 反选(swarm-guard 同款分段提取:&&/||/;/|/换行 分段、跳过全局选项、提取不到
|
|
578
|
+
* 动词 fail-closed 拒):仅禁变更动词与双态动词的变更子形态(见 GIT_STANDALONE_DENY_VERBS
|
|
579
|
+
* /standaloneGitDenyReason),查询、clone/fetch、裸 checkout/switch 放行;非 git 段不因
|
|
580
|
+
* git 规则拒绝;最后挂只读基座 buildReadOnlyWriteGuard(写动词/重定向照拒;clone/fetch
|
|
581
|
+
* 落盘是 git 自身行为,BASH_WRITE_RE 无此二动词天然放行,无需特判);
|
|
582
|
+
* 3. wiki_write(独立模式)→ 仅放行 projects/<repo>/reviews/<主题>-<日期>/ 命名空间;
|
|
583
|
+
* 4. wiki_write(非独立会话)→ 链上组合会话(isRoleComposed)放行(自有 agent-scope
|
|
584
|
+
* guard 管,链命名空间写入绝不被本 guard 误拦);其余(main/swarm/未知 GUI)拒绝
|
|
585
|
+
* ——评审工具全局注册后 wiki_write 收紧到评审会话;
|
|
586
|
+
* 5. 其余工具(read/glob/grep/ocr_review/wiki_read/wiki_search 等)→ 放行。 */
|
|
587
|
+
export function buildStandaloneDtGuard() {
|
|
588
|
+
return (execution) => {
|
|
589
|
+
const header = extractSessionHeader(execution?.agent);
|
|
590
|
+
const name = String(execution?.name ?? '');
|
|
591
|
+
const agent = execution?.agent;
|
|
592
|
+
const sessionId = typeof agent?.id === 'string' ? agent.id : undefined;
|
|
593
|
+
// 链上系 DT 子代理(parentSession 为 kbn-<taskId> 前缀):交由 buildSubagentTreeGuard 管,
|
|
594
|
+
// 本 guard 不按独立模式收紧、也不在非独立分支拒其 wiki_write(链评审目录写入归该 guard 校验)。
|
|
595
|
+
const isDtChainSubagent = !!header
|
|
596
|
+
&& header.agentPreset === 'kanban-dt'
|
|
597
|
+
&& typeof header.parentSession === 'string'
|
|
598
|
+
&& header.parentSession.startsWith('kbn-');
|
|
599
|
+
const standalone = !!header
|
|
600
|
+
&& header.agentPreset === 'kanban-dt'
|
|
601
|
+
&& !isRoleComposed(execution?.agent)
|
|
602
|
+
&& !isDtChainSubagent
|
|
603
|
+
&& !(sessionId !== undefined && sessionId.startsWith('kbn-'));
|
|
604
|
+
if (standalone) {
|
|
605
|
+
if (name === 'kanban_complete' || name === 'kanban_block' || name === 'kanban_comment' || name === 'kanban_heartbeat' || name === 'kanban_create') {
|
|
606
|
+
return 'standalone-dt: 独立评审模式不使用看板工具';
|
|
607
|
+
}
|
|
608
|
+
if (name === 'bash' || name === 'run_code' || name === 'write' || name === 'edit') {
|
|
609
|
+
const args = execution?.arguments ?? {};
|
|
610
|
+
// 扩权参数教学拦截:独立评审只读无扩权场景,宿主 bash/write/edit schema 仍广播
|
|
611
|
+
// sandbox_permissions/justification(组合层行为,会话层改不掉),模型重试惯性带参
|
|
612
|
+
// 会触发宿主沙箱校验错误(invalid justification)——在此拦下并教模型去参重试。
|
|
613
|
+
if (args && typeof args === 'object' && ESCALATION_PARAM_KEYS.some((k) => args[k] !== undefined)) {
|
|
614
|
+
return 'standalone-dt: 独立评审为只读会话——不要传 sandbox_permissions/justification 扩权参数(会触发宿主沙箱校验错误);去掉该参数后重试';
|
|
615
|
+
}
|
|
616
|
+
if (name === 'bash' || name === 'run_code') {
|
|
617
|
+
const cmd = String(args['command'] ?? args['code'] ?? '');
|
|
618
|
+
if (cmd) {
|
|
619
|
+
const segments = cmd.split(/\s*(?:&&|\|\||;|\||\n)\s*/);
|
|
620
|
+
for (const seg of segments) {
|
|
621
|
+
if (!/\bgit\b/.test(seg))
|
|
622
|
+
continue;
|
|
623
|
+
const m = seg.match(GIT_VERB_RE);
|
|
624
|
+
const verb = m?.[1];
|
|
625
|
+
// 反选:仅禁变更动词与双态动词的变更子形态;提取不到动词 fail-closed 拒
|
|
626
|
+
if (!verb || GIT_MUTATION_VERBS.has(verb))
|
|
627
|
+
return STANDALONE_GIT_DENY;
|
|
628
|
+
const sub = dualVerbGitDenyReason(verb, seg.slice((m.index ?? 0) + m[0].length), STANDALONE_GIT_DENY);
|
|
629
|
+
if (sub)
|
|
630
|
+
return sub;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
const baseReason = buildReadOnlyWriteGuard(header.cwd || '/')(execution);
|
|
634
|
+
if (baseReason)
|
|
635
|
+
return baseReason;
|
|
636
|
+
}
|
|
637
|
+
return undefined;
|
|
638
|
+
}
|
|
639
|
+
if (name === 'wiki_write') {
|
|
640
|
+
const args = execution?.arguments ?? {};
|
|
641
|
+
const pagePath = String(args && typeof args === 'object' ? args['pagePath'] ?? '' : '');
|
|
642
|
+
if (!isStandaloneReviewNamespacePath(pagePath))
|
|
643
|
+
return 'wiki-write-outside-reviews-namespace: 独立评审仅可写 projects/<repo>/reviews/<主题>-<日期>/';
|
|
644
|
+
return undefined;
|
|
645
|
+
}
|
|
646
|
+
return undefined;
|
|
647
|
+
}
|
|
648
|
+
if (name === 'wiki_write') {
|
|
649
|
+
if (isRoleComposed(execution?.agent) || isDtChainSubagent)
|
|
650
|
+
return undefined;
|
|
651
|
+
return 'wiki-write-restricted-to-reviewer-sessions: wiki_write 仅限交付评审官(DT)评审会话使用';
|
|
652
|
+
}
|
|
653
|
+
return undefined;
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
/** 独立评审工具全局注册:ocr_review + wiki 三原语(wiki_read/wiki_search/wiki_write)。
|
|
657
|
+
* 独立评审不经 agent-runner 角色组合,角色工具面不存在,故在插件全局 ctx 注册;
|
|
658
|
+
* caller 固定 actor='dt'(can('wiki-write','dt')=true),wiki_write 的会话级收紧由
|
|
659
|
+
* buildStandaloneDtGuard 完成(链上组合会话放行,main/swarm/未知 GUI 拒绝)。
|
|
660
|
+
* wiki 客户端按 kbMode 构造(与 registerMainSessionTools 同源:remote 优先 ctx.get('wiki')
|
|
661
|
+
* 注入(测试 mock),生产热读取 getEffective().wikiVault;local 走 LocalWikiClient)。
|
|
662
|
+
* local 模式不注册 wiki_write:LocalWikiClient.abs 只接受 wiki/** 形态,而 wiki_write
|
|
663
|
+
* 工具边界只放行 projects/... 命名空间——双锁死(任何路径都写不进)。与链上 DT local
|
|
664
|
+
* 行为一致(走 skill/fs 工具而非 wiki 原语);wiki_read/wiki_search 不受写路径白名单
|
|
665
|
+
* 约束,照常注册。
|
|
666
|
+
* registry 缺失(测试裸 Context)→ return,与 registerMainSessionTools 同款防御。 */
|
|
667
|
+
export function registerStandaloneReviewerTools(ctx, configProvider) {
|
|
668
|
+
const registry = ctx.get('tools');
|
|
669
|
+
if (!registry)
|
|
670
|
+
return; // 测试裸 Context 无 tools 服务,跳过注册
|
|
671
|
+
registry.register(buildOcrReviewTool({ cwd: () => process.cwd() }));
|
|
672
|
+
const kbMode = configProvider.mode;
|
|
673
|
+
const wiki = (kbMode === 'local'
|
|
674
|
+
? new LocalWikiClient(ensureLocalKbRoot())
|
|
675
|
+
: (ctx.get('wiki') ?? new WikiVaultClient(() => configProvider.getEffective().wikiVault)));
|
|
676
|
+
const caller = () => ({ actor: 'dt' });
|
|
677
|
+
for (const tool of buildWikiTools(wiki, caller)) {
|
|
678
|
+
if (kbMode === 'local' && tool.name === 'wiki_write')
|
|
679
|
+
continue;
|
|
680
|
+
registry.register(tool);
|
|
681
|
+
}
|
|
682
|
+
}
|