@cleocode/cleo 2026.4.158 → 2026.5.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/dist/backfill/audit-columns.d.ts +105 -0
- package/dist/backfill/audit-columns.d.ts.map +1 -0
- package/dist/backfill/audit-columns.js +258 -0
- package/dist/backfill/audit-columns.js.map +1 -0
- package/dist/cli/commands/adapter.d.ts +28 -0
- package/dist/cli/commands/adapter.d.ts.map +1 -0
- package/dist/cli/commands/adapter.js +119 -0
- package/dist/cli/commands/adapter.js.map +1 -0
- package/dist/cli/commands/add-batch.d.ts +33 -0
- package/dist/cli/commands/add-batch.d.ts.map +1 -0
- package/dist/cli/commands/add-batch.js +148 -0
- package/dist/cli/commands/add-batch.js.map +1 -0
- package/dist/cli/commands/add.d.ts +162 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +279 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +24 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +283 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/adr.d.ts +33 -0
- package/dist/cli/commands/adr.d.ts.map +1 -0
- package/dist/cli/commands/adr.js +147 -0
- package/dist/cli/commands/adr.js.map +1 -0
- package/dist/cli/commands/agent-profile-status.d.ts +98 -0
- package/dist/cli/commands/agent-profile-status.d.ts.map +1 -0
- package/dist/cli/commands/agent-profile-status.js +71 -0
- package/dist/cli/commands/agent-profile-status.js.map +1 -0
- package/dist/cli/commands/agent.d.ts +47 -0
- package/dist/cli/commands/agent.d.ts.map +1 -0
- package/dist/cli/commands/agent.js +2976 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/analyze.d.ts +21 -0
- package/dist/cli/commands/analyze.d.ts.map +1 -0
- package/dist/cli/commands/analyze.js +32 -0
- package/dist/cli/commands/analyze.js.map +1 -0
- package/dist/cli/commands/archive-stats.d.ts +66 -0
- package/dist/cli/commands/archive-stats.d.ts.map +1 -0
- package/dist/cli/commands/archive-stats.js +93 -0
- package/dist/cli/commands/archive-stats.js.map +1 -0
- package/dist/cli/commands/archive.d.ts +42 -0
- package/dist/cli/commands/archive.d.ts.map +1 -0
- package/dist/cli/commands/archive.js +59 -0
- package/dist/cli/commands/archive.js.map +1 -0
- package/dist/cli/commands/audit.d.ts +22 -0
- package/dist/cli/commands/audit.d.ts.map +1 -0
- package/dist/cli/commands/audit.js +137 -0
- package/dist/cli/commands/audit.js.map +1 -0
- package/dist/cli/commands/backfill.d.ts +56 -0
- package/dist/cli/commands/backfill.d.ts.map +1 -0
- package/dist/cli/commands/backfill.js +161 -0
- package/dist/cli/commands/backfill.js.map +1 -0
- package/dist/cli/commands/backup-inspect.d.ts +33 -0
- package/dist/cli/commands/backup-inspect.d.ts.map +1 -0
- package/dist/cli/commands/backup-inspect.js +430 -0
- package/dist/cli/commands/backup-inspect.js.map +1 -0
- package/dist/cli/commands/backup.d.ts +23 -0
- package/dist/cli/commands/backup.d.ts.map +1 -0
- package/dist/cli/commands/backup.js +564 -0
- package/dist/cli/commands/backup.js.map +1 -0
- package/dist/cli/commands/blockers.d.ts +20 -0
- package/dist/cli/commands/blockers.d.ts.map +1 -0
- package/dist/cli/commands/blockers.js +31 -0
- package/dist/cli/commands/blockers.js.map +1 -0
- package/dist/cli/commands/brain.d.ts +37 -0
- package/dist/cli/commands/brain.d.ts.map +1 -0
- package/dist/cli/commands/brain.js +445 -0
- package/dist/cli/commands/brain.js.map +1 -0
- package/dist/cli/commands/briefing.d.ts +52 -0
- package/dist/cli/commands/briefing.d.ts.map +1 -0
- package/dist/cli/commands/briefing.js +69 -0
- package/dist/cli/commands/briefing.js.map +1 -0
- package/dist/cli/commands/bug.d.ts +61 -0
- package/dist/cli/commands/bug.d.ts.map +1 -0
- package/dist/cli/commands/bug.js +198 -0
- package/dist/cli/commands/bug.js.map +1 -0
- package/dist/cli/commands/cancel.d.ts +26 -0
- package/dist/cli/commands/cancel.d.ts.map +1 -0
- package/dist/cli/commands/cancel.js +40 -0
- package/dist/cli/commands/cancel.js.map +1 -0
- package/dist/cli/commands/cant.d.ts +13 -0
- package/dist/cli/commands/cant.d.ts.map +1 -0
- package/dist/cli/commands/cant.js +245 -0
- package/dist/cli/commands/cant.js.map +1 -0
- package/dist/cli/commands/chain.d.ts +24 -0
- package/dist/cli/commands/chain.d.ts.map +1 -0
- package/dist/cli/commands/chain.js +116 -0
- package/dist/cli/commands/chain.js.map +1 -0
- package/dist/cli/commands/check.d.ts +18 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +280 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/checkpoint.d.ts +27 -0
- package/dist/cli/commands/checkpoint.d.ts.map +1 -0
- package/dist/cli/commands/checkpoint.js +105 -0
- package/dist/cli/commands/checkpoint.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +35 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +35 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/code.d.ts +22 -0
- package/dist/cli/commands/code.d.ts.map +1 -0
- package/dist/cli/commands/code.js +161 -0
- package/dist/cli/commands/code.js.map +1 -0
- package/dist/cli/commands/complete.d.ts +49 -0
- package/dist/cli/commands/complete.d.ts.map +1 -0
- package/dist/cli/commands/complete.js +83 -0
- package/dist/cli/commands/complete.js.map +1 -0
- package/dist/cli/commands/complexity.d.ts +13 -0
- package/dist/cli/commands/complexity.d.ts.map +1 -0
- package/dist/cli/commands/complexity.js +32 -0
- package/dist/cli/commands/complexity.js.map +1 -0
- package/dist/cli/commands/compliance.d.ts +27 -0
- package/dist/cli/commands/compliance.d.ts.map +1 -0
- package/dist/cli/commands/compliance.js +233 -0
- package/dist/cli/commands/compliance.js.map +1 -0
- package/dist/cli/commands/conduit.d.ts +28 -0
- package/dist/cli/commands/conduit.d.ts.map +1 -0
- package/dist/cli/commands/conduit.js +279 -0
- package/dist/cli/commands/conduit.js.map +1 -0
- package/dist/cli/commands/config.d.ts +25 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +132 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/consensus.d.ts +21 -0
- package/dist/cli/commands/consensus.d.ts.map +1 -0
- package/dist/cli/commands/consensus.js +100 -0
- package/dist/cli/commands/consensus.js.map +1 -0
- package/dist/cli/commands/context.d.ts +19 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +111 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/contribution.d.ts +21 -0
- package/dist/cli/commands/contribution.d.ts.map +1 -0
- package/dist/cli/commands/contribution.js +90 -0
- package/dist/cli/commands/contribution.js.map +1 -0
- package/dist/cli/commands/current.d.ts +18 -0
- package/dist/cli/commands/current.d.ts.map +1 -0
- package/dist/cli/commands/current.js +28 -0
- package/dist/cli/commands/current.js.map +1 -0
- package/dist/cli/commands/daemon.d.ts +36 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -0
- package/dist/cli/commands/daemon.js +223 -0
- package/dist/cli/commands/daemon.js.map +1 -0
- package/dist/cli/commands/dash.d.ts +23 -0
- package/dist/cli/commands/dash.d.ts.map +1 -0
- package/dist/cli/commands/dash.js +38 -0
- package/dist/cli/commands/dash.js.map +1 -0
- package/dist/cli/commands/decomposition.d.ts +13 -0
- package/dist/cli/commands/decomposition.d.ts.map +1 -0
- package/dist/cli/commands/decomposition.js +92 -0
- package/dist/cli/commands/decomposition.js.map +1 -0
- package/dist/cli/commands/delete.d.ts +29 -0
- package/dist/cli/commands/delete.d.ts.map +1 -0
- package/dist/cli/commands/delete.js +55 -0
- package/dist/cli/commands/delete.js.map +1 -0
- package/dist/cli/commands/deps.d.ts +45 -0
- package/dist/cli/commands/deps.d.ts.map +1 -0
- package/dist/cli/commands/deps.js +170 -0
- package/dist/cli/commands/deps.js.map +1 -0
- package/dist/cli/commands/detect-drift.d.ts +23 -0
- package/dist/cli/commands/detect-drift.d.ts.map +1 -0
- package/dist/cli/commands/detect-drift.js +440 -0
- package/dist/cli/commands/detect-drift.js.map +1 -0
- package/dist/cli/commands/detect.d.ts +3 -0
- package/dist/cli/commands/detect.d.ts.map +1 -0
- package/dist/cli/commands/detect.js +14 -0
- package/dist/cli/commands/detect.js.map +1 -0
- package/dist/cli/commands/diagnostics.d.ts +19 -0
- package/dist/cli/commands/diagnostics.d.ts.map +1 -0
- package/dist/cli/commands/diagnostics.js +109 -0
- package/dist/cli/commands/diagnostics.js.map +1 -0
- package/dist/cli/commands/docs.d.ts +25 -0
- package/dist/cli/commands/docs.d.ts.map +1 -0
- package/dist/cli/commands/docs.js +798 -0
- package/dist/cli/commands/docs.js.map +1 -0
- package/dist/cli/commands/doctor-projects.d.ts +101 -0
- package/dist/cli/commands/doctor-projects.d.ts.map +1 -0
- package/dist/cli/commands/doctor-projects.js +188 -0
- package/dist/cli/commands/doctor-projects.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +66 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +178 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/dynamic.d.ts +15 -0
- package/dist/cli/commands/dynamic.d.ts.map +1 -0
- package/dist/cli/commands/dynamic.js +21 -0
- package/dist/cli/commands/dynamic.js.map +1 -0
- package/dist/cli/commands/exists.d.ts +13 -0
- package/dist/cli/commands/exists.d.ts.map +1 -0
- package/dist/cli/commands/exists.js +40 -0
- package/dist/cli/commands/exists.js.map +1 -0
- package/dist/cli/commands/export-tasks.d.ts +46 -0
- package/dist/cli/commands/export-tasks.d.ts.map +1 -0
- package/dist/cli/commands/export-tasks.js +81 -0
- package/dist/cli/commands/export-tasks.js.map +1 -0
- package/dist/cli/commands/export.d.ts +35 -0
- package/dist/cli/commands/export.d.ts.map +1 -0
- package/dist/cli/commands/export.js +68 -0
- package/dist/cli/commands/export.js.map +1 -0
- package/dist/cli/commands/find.d.ts +54 -0
- package/dist/cli/commands/find.d.ts.map +1 -0
- package/dist/cli/commands/find.js +92 -0
- package/dist/cli/commands/find.js.map +1 -0
- package/dist/cli/commands/gc.d.ts +25 -0
- package/dist/cli/commands/gc.d.ts.map +1 -0
- package/dist/cli/commands/gc.js +165 -0
- package/dist/cli/commands/gc.js.map +1 -0
- package/dist/cli/commands/generate-changelog.d.ts +30 -0
- package/dist/cli/commands/generate-changelog.d.ts.map +1 -0
- package/dist/cli/commands/generate-changelog.js +270 -0
- package/dist/cli/commands/generate-changelog.js.map +1 -0
- package/dist/cli/commands/grade.d.ts +13 -0
- package/dist/cli/commands/grade.d.ts.map +1 -0
- package/dist/cli/commands/grade.js +27 -0
- package/dist/cli/commands/grade.js.map +1 -0
- package/dist/cli/commands/history.d.ts +13 -0
- package/dist/cli/commands/history.d.ts.map +1 -0
- package/dist/cli/commands/history.js +65 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/import-tasks.d.ts +60 -0
- package/dist/cli/commands/import-tasks.d.ts.map +1 -0
- package/dist/cli/commands/import-tasks.js +83 -0
- package/dist/cli/commands/import-tasks.js.map +1 -0
- package/dist/cli/commands/import.d.ts +42 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +64 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +65 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +122 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/inject.d.ts +41 -0
- package/dist/cli/commands/inject.d.ts.map +1 -0
- package/dist/cli/commands/inject.js +56 -0
- package/dist/cli/commands/inject.js.map +1 -0
- package/dist/cli/commands/install-global.d.ts +48 -0
- package/dist/cli/commands/install-global.d.ts.map +1 -0
- package/dist/cli/commands/install-global.js +104 -0
- package/dist/cli/commands/install-global.js.map +1 -0
- package/dist/cli/commands/intelligence.d.ts +21 -0
- package/dist/cli/commands/intelligence.d.ts.map +1 -0
- package/dist/cli/commands/intelligence.js +145 -0
- package/dist/cli/commands/intelligence.js.map +1 -0
- package/dist/cli/commands/issue.d.ts +23 -0
- package/dist/cli/commands/issue.d.ts.map +1 -0
- package/dist/cli/commands/issue.js +152 -0
- package/dist/cli/commands/issue.js.map +1 -0
- package/dist/cli/commands/labels.d.ts +21 -0
- package/dist/cli/commands/labels.d.ts.map +1 -0
- package/dist/cli/commands/labels.js +65 -0
- package/dist/cli/commands/labels.js.map +1 -0
- package/dist/cli/commands/lifecycle.d.ts +25 -0
- package/dist/cli/commands/lifecycle.d.ts.map +1 -0
- package/dist/cli/commands/lifecycle.js +221 -0
- package/dist/cli/commands/lifecycle.js.map +1 -0
- package/dist/cli/commands/list.d.ts +28 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +81 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/log.d.ts +36 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +50 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/manifest.d.ts +15 -0
- package/dist/cli/commands/manifest.d.ts.map +1 -0
- package/dist/cli/commands/manifest.js +334 -0
- package/dist/cli/commands/manifest.js.map +1 -0
- package/dist/cli/commands/map.d.ts +25 -0
- package/dist/cli/commands/map.d.ts.map +1 -0
- package/dist/cli/commands/map.js +37 -0
- package/dist/cli/commands/map.js.map +1 -0
- package/dist/cli/commands/memory.d.ts +48 -0
- package/dist/cli/commands/memory.d.ts.map +1 -0
- package/dist/cli/commands/memory.js +2439 -0
- package/dist/cli/commands/memory.js.map +1 -0
- package/dist/cli/commands/migrate-claude-mem.d.ts +23 -0
- package/dist/cli/commands/migrate-claude-mem.d.ts.map +1 -0
- package/dist/cli/commands/migrate-claude-mem.js +181 -0
- package/dist/cli/commands/migrate-claude-mem.js.map +1 -0
- package/dist/cli/commands/next.d.ts +27 -0
- package/dist/cli/commands/next.d.ts.map +1 -0
- package/dist/cli/commands/next.js +40 -0
- package/dist/cli/commands/next.js.map +1 -0
- package/dist/cli/commands/nexus.d.ts +15 -0
- package/dist/cli/commands/nexus.d.ts.map +1 -0
- package/dist/cli/commands/nexus.js +3377 -0
- package/dist/cli/commands/nexus.js.map +1 -0
- package/dist/cli/commands/ops.d.ts +23 -0
- package/dist/cli/commands/ops.d.ts.map +1 -0
- package/dist/cli/commands/ops.js +35 -0
- package/dist/cli/commands/ops.js.map +1 -0
- package/dist/cli/commands/orchestrate.d.ts +48 -0
- package/dist/cli/commands/orchestrate.d.ts.map +1 -0
- package/dist/cli/commands/orchestrate.js +774 -0
- package/dist/cli/commands/orchestrate.js.map +1 -0
- package/dist/cli/commands/otel.d.ts +30 -0
- package/dist/cli/commands/otel.d.ts.map +1 -0
- package/dist/cli/commands/otel.js +193 -0
- package/dist/cli/commands/otel.js.map +1 -0
- package/dist/cli/commands/phase.d.ts +29 -0
- package/dist/cli/commands/phase.d.ts.map +1 -0
- package/dist/cli/commands/phase.js +189 -0
- package/dist/cli/commands/phase.js.map +1 -0
- package/dist/cli/commands/pivot.d.ts +34 -0
- package/dist/cli/commands/pivot.d.ts.map +1 -0
- package/dist/cli/commands/pivot.js +50 -0
- package/dist/cli/commands/pivot.js.map +1 -0
- package/dist/cli/commands/plan.d.ts +17 -0
- package/dist/cli/commands/plan.d.ts.map +1 -0
- package/dist/cli/commands/plan.js +27 -0
- package/dist/cli/commands/plan.js.map +1 -0
- package/dist/cli/commands/playbook.d.ts +26 -0
- package/dist/cli/commands/playbook.d.ts.map +1 -0
- package/dist/cli/commands/playbook.js +220 -0
- package/dist/cli/commands/playbook.js.map +1 -0
- package/dist/cli/commands/promote.d.ts +19 -0
- package/dist/cli/commands/promote.d.ts.map +1 -0
- package/dist/cli/commands/promote.js +27 -0
- package/dist/cli/commands/promote.js.map +1 -0
- package/dist/cli/commands/provider.d.ts +23 -0
- package/dist/cli/commands/provider.d.ts.map +1 -0
- package/dist/cli/commands/provider.js +168 -0
- package/dist/cli/commands/provider.js.map +1 -0
- package/dist/cli/commands/reason.d.ts +18 -0
- package/dist/cli/commands/reason.d.ts.map +1 -0
- package/dist/cli/commands/reason.js +102 -0
- package/dist/cli/commands/reason.js.map +1 -0
- package/dist/cli/commands/reconcile.d.ts +35 -0
- package/dist/cli/commands/reconcile.d.ts.map +1 -0
- package/dist/cli/commands/reconcile.js +102 -0
- package/dist/cli/commands/reconcile.js.map +1 -0
- package/dist/cli/commands/refresh-memory.d.ts +16 -0
- package/dist/cli/commands/refresh-memory.d.ts.map +1 -0
- package/dist/cli/commands/refresh-memory.js +34 -0
- package/dist/cli/commands/refresh-memory.js.map +1 -0
- package/dist/cli/commands/relates.d.ts +19 -0
- package/dist/cli/commands/relates.d.ts.map +1 -0
- package/dist/cli/commands/relates.js +129 -0
- package/dist/cli/commands/relates.js.map +1 -0
- package/dist/cli/commands/release.d.ts +27 -0
- package/dist/cli/commands/release.d.ts.map +1 -0
- package/dist/cli/commands/release.js +300 -0
- package/dist/cli/commands/release.js.map +1 -0
- package/dist/cli/commands/remote.d.ts +49 -0
- package/dist/cli/commands/remote.d.ts.map +1 -0
- package/dist/cli/commands/remote.js +265 -0
- package/dist/cli/commands/remote.js.map +1 -0
- package/dist/cli/commands/reorder.d.ts +31 -0
- package/dist/cli/commands/reorder.d.ts.map +1 -0
- package/dist/cli/commands/reorder.js +57 -0
- package/dist/cli/commands/reorder.js.map +1 -0
- package/dist/cli/commands/reparent.d.ts +27 -0
- package/dist/cli/commands/reparent.d.ts.map +1 -0
- package/dist/cli/commands/reparent.js +36 -0
- package/dist/cli/commands/reparent.js.map +1 -0
- package/dist/cli/commands/req.d.ts +37 -0
- package/dist/cli/commands/req.d.ts.map +1 -0
- package/dist/cli/commands/req.js +121 -0
- package/dist/cli/commands/req.js.map +1 -0
- package/dist/cli/commands/research.d.ts +25 -0
- package/dist/cli/commands/research.d.ts.map +1 -0
- package/dist/cli/commands/research.js +327 -0
- package/dist/cli/commands/research.js.map +1 -0
- package/dist/cli/commands/restore.d.ts +64 -0
- package/dist/cli/commands/restore.d.ts.map +1 -0
- package/dist/cli/commands/restore.js +539 -0
- package/dist/cli/commands/restore.js.map +1 -0
- package/dist/cli/commands/revert.d.ts +79 -0
- package/dist/cli/commands/revert.d.ts.map +1 -0
- package/dist/cli/commands/revert.js +300 -0
- package/dist/cli/commands/revert.js.map +1 -0
- package/dist/cli/commands/roadmap.d.ts +29 -0
- package/dist/cli/commands/roadmap.d.ts.map +1 -0
- package/dist/cli/commands/roadmap.js +43 -0
- package/dist/cli/commands/roadmap.js.map +1 -0
- package/dist/cli/commands/safestop.d.ts +41 -0
- package/dist/cli/commands/safestop.d.ts.map +1 -0
- package/dist/cli/commands/safestop.js +62 -0
- package/dist/cli/commands/safestop.js.map +1 -0
- package/dist/cli/commands/schema.d.ts +44 -0
- package/dist/cli/commands/schema.d.ts.map +1 -0
- package/dist/cli/commands/schema.js +177 -0
- package/dist/cli/commands/schema.js.map +1 -0
- package/dist/cli/commands/self-update.d.ts +81 -0
- package/dist/cli/commands/self-update.d.ts.map +1 -0
- package/dist/cli/commands/self-update.js +483 -0
- package/dist/cli/commands/self-update.js.map +1 -0
- package/dist/cli/commands/sentient.d.ts +44 -0
- package/dist/cli/commands/sentient.d.ts.map +1 -0
- package/dist/cli/commands/sentient.js +687 -0
- package/dist/cli/commands/sentient.js.map +1 -0
- package/dist/cli/commands/sequence.d.ts +15 -0
- package/dist/cli/commands/sequence.d.ts.map +1 -0
- package/dist/cli/commands/sequence.js +68 -0
- package/dist/cli/commands/sequence.js.map +1 -0
- package/dist/cli/commands/session.d.ts +32 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +583 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/show.d.ts +21 -0
- package/dist/cli/commands/show.d.ts.map +1 -0
- package/dist/cli/commands/show.js +37 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/skills.d.ts +31 -0
- package/dist/cli/commands/skills.d.ts.map +1 -0
- package/dist/cli/commands/skills.js +303 -0
- package/dist/cli/commands/skills.js.map +1 -0
- package/dist/cli/commands/snapshot.d.ts +17 -0
- package/dist/cli/commands/snapshot.d.ts.map +1 -0
- package/dist/cli/commands/snapshot.js +95 -0
- package/dist/cli/commands/snapshot.js.map +1 -0
- package/dist/cli/commands/start.d.ts +21 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +32 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +30 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +71 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/sticky.d.ts +23 -0
- package/dist/cli/commands/sticky.d.ts.map +1 -0
- package/dist/cli/commands/sticky.js +315 -0
- package/dist/cli/commands/sticky.js.map +1 -0
- package/dist/cli/commands/stop.d.ts +15 -0
- package/dist/cli/commands/stop.d.ts.map +1 -0
- package/dist/cli/commands/stop.js +25 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +25 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +125 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/testing.d.ts +22 -0
- package/dist/cli/commands/testing.d.ts.map +1 -0
- package/dist/cli/commands/testing.js +111 -0
- package/dist/cli/commands/testing.js.map +1 -0
- package/dist/cli/commands/token.d.ts +22 -0
- package/dist/cli/commands/token.d.ts.map +1 -0
- package/dist/cli/commands/token.js +197 -0
- package/dist/cli/commands/token.js.map +1 -0
- package/dist/cli/commands/transcript.d.ts +32 -0
- package/dist/cli/commands/transcript.d.ts.map +1 -0
- package/dist/cli/commands/transcript.js +526 -0
- package/dist/cli/commands/transcript.js.map +1 -0
- package/dist/cli/commands/update.d.ts +164 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +234 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/upgrade.d.ts +76 -0
- package/dist/cli/commands/upgrade.d.ts.map +1 -0
- package/dist/cli/commands/upgrade.js +154 -0
- package/dist/cli/commands/upgrade.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +83 -0
- package/dist/cli/commands/verify.d.ts.map +1 -0
- package/dist/cli/commands/verify.js +108 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/commands/web.d.ts +27 -0
- package/dist/cli/commands/web.d.ts.map +1 -0
- package/dist/cli/commands/web.js +414 -0
- package/dist/cli/commands/web.js.map +1 -0
- package/dist/cli/field-context.d.ts +32 -0
- package/dist/cli/field-context.d.ts.map +1 -0
- package/dist/cli/field-context.js +47 -0
- package/dist/cli/field-context.js.map +1 -0
- package/dist/cli/format-context.d.ts +32 -0
- package/dist/cli/format-context.d.ts.map +1 -0
- package/dist/cli/format-context.js +50 -0
- package/dist/cli/format-context.js.map +1 -0
- package/dist/cli/help-renderer.d.ts +40 -0
- package/dist/cli/help-renderer.d.ts.map +1 -0
- package/dist/cli/help-renderer.js +325 -0
- package/dist/cli/help-renderer.js.map +1 -0
- package/dist/cli/index.d.ts +14 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +1535 -9704
- package/dist/cli/index.js.map +4 -4
- package/dist/cli/infer-files-via-gitnexus.d.ts +12 -0
- package/dist/cli/infer-files-via-gitnexus.d.ts.map +1 -0
- package/dist/cli/infer-files-via-gitnexus.js +12 -0
- package/dist/cli/infer-files-via-gitnexus.js.map +1 -0
- package/dist/cli/lib/did-you-mean.d.ts +30 -0
- package/dist/cli/lib/did-you-mean.d.ts.map +1 -0
- package/dist/cli/lib/did-you-mean.js +63 -0
- package/dist/cli/lib/did-you-mean.js.map +1 -0
- package/dist/cli/lib/registry-args.d.ts +36 -0
- package/dist/cli/lib/registry-args.d.ts.map +1 -0
- package/dist/cli/lib/registry-args.js +37 -0
- package/dist/cli/lib/registry-args.js.map +1 -0
- package/dist/cli/lib/subcommand-guard.d.ts +45 -0
- package/dist/cli/lib/subcommand-guard.d.ts.map +1 -0
- package/dist/cli/lib/subcommand-guard.js +55 -0
- package/dist/cli/lib/subcommand-guard.js.map +1 -0
- package/dist/cli/logger-bootstrap.d.ts +6 -0
- package/dist/cli/logger-bootstrap.d.ts.map +1 -0
- package/dist/cli/logger-bootstrap.js +10 -0
- package/dist/cli/logger-bootstrap.js.map +1 -0
- package/dist/cli/middleware/output-format.d.ts +30 -0
- package/dist/cli/middleware/output-format.d.ts.map +1 -0
- package/dist/cli/middleware/output-format.js +35 -0
- package/dist/cli/middleware/output-format.js.map +1 -0
- package/dist/cli/paths.d.ts +85 -0
- package/dist/cli/paths.d.ts.map +1 -0
- package/dist/cli/paths.js +108 -0
- package/dist/cli/paths.js.map +1 -0
- package/dist/cli/progress.d.ts +89 -0
- package/dist/cli/progress.d.ts.map +1 -0
- package/dist/cli/progress.js +185 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/renderers/colors.d.ts +32 -0
- package/dist/cli/renderers/colors.d.ts.map +1 -0
- package/dist/cli/renderers/colors.js +141 -0
- package/dist/cli/renderers/colors.js.map +1 -0
- package/dist/cli/renderers/error.d.ts +13 -0
- package/dist/cli/renderers/error.d.ts.map +1 -0
- package/dist/cli/renderers/error.js +42 -0
- package/dist/cli/renderers/error.js.map +1 -0
- package/dist/cli/renderers/index.d.ts +90 -0
- package/dist/cli/renderers/index.d.ts.map +1 -0
- package/dist/cli/renderers/index.js +268 -0
- package/dist/cli/renderers/index.js.map +1 -0
- package/dist/cli/renderers/lafs-validator.d.ts +91 -0
- package/dist/cli/renderers/lafs-validator.d.ts.map +1 -0
- package/dist/cli/renderers/lafs-validator.js +176 -0
- package/dist/cli/renderers/lafs-validator.js.map +1 -0
- package/dist/cli/renderers/normalizer.d.ts +21 -0
- package/dist/cli/renderers/normalizer.d.ts.map +1 -0
- package/dist/cli/renderers/normalizer.js +106 -0
- package/dist/cli/renderers/normalizer.js.map +1 -0
- package/dist/cli/renderers/system.d.ts +110 -0
- package/dist/cli/renderers/system.d.ts.map +1 -0
- package/dist/cli/renderers/system.js +662 -0
- package/dist/cli/renderers/system.js.map +1 -0
- package/dist/cli/renderers/tasks.d.ts +28 -0
- package/dist/cli/renderers/tasks.d.ts.map +1 -0
- package/dist/cli/renderers/tasks.js +306 -0
- package/dist/cli/renderers/tasks.js.map +1 -0
- package/dist/cli/tree-context.d.ts +53 -0
- package/dist/cli/tree-context.d.ts.map +1 -0
- package/dist/cli/tree-context.js +43 -0
- package/dist/cli/tree-context.js.map +1 -0
- package/dist/dispatch/adapters/cli.d.ts +67 -0
- package/dist/dispatch/adapters/cli.d.ts.map +1 -0
- package/dist/dispatch/adapters/cli.js +331 -0
- package/dist/dispatch/adapters/cli.js.map +1 -0
- package/dist/dispatch/adapters/typed.d.ts +362 -0
- package/dist/dispatch/adapters/typed.d.ts.map +1 -0
- package/dist/dispatch/adapters/typed.js +278 -0
- package/dist/dispatch/adapters/typed.js.map +1 -0
- package/dist/dispatch/context/session-context.d.ts +108 -0
- package/dist/dispatch/context/session-context.d.ts.map +1 -0
- package/dist/dispatch/context/session-context.js +111 -0
- package/dist/dispatch/context/session-context.js.map +1 -0
- package/dist/dispatch/dispatcher.d.ts +37 -0
- package/dist/dispatch/dispatcher.d.ts.map +1 -0
- package/dist/dispatch/dispatcher.js +172 -0
- package/dist/dispatch/dispatcher.js.map +1 -0
- package/dist/dispatch/domains/_base.d.ts +104 -0
- package/dist/dispatch/domains/_base.d.ts.map +1 -0
- package/dist/dispatch/domains/_base.js +147 -0
- package/dist/dispatch/domains/_base.js.map +1 -0
- package/dist/dispatch/domains/_meta.d.ts +23 -0
- package/dist/dispatch/domains/_meta.d.ts.map +1 -0
- package/dist/dispatch/domains/_meta.js +25 -0
- package/dist/dispatch/domains/_meta.js.map +1 -0
- package/dist/dispatch/domains/_routing.d.ts +8 -0
- package/dist/dispatch/domains/_routing.d.ts.map +1 -0
- package/dist/dispatch/domains/_routing.js +20 -0
- package/dist/dispatch/domains/_routing.js.map +1 -0
- package/dist/dispatch/domains/admin/smoke-provider.d.ts +54 -0
- package/dist/dispatch/domains/admin/smoke-provider.d.ts.map +1 -0
- package/dist/dispatch/domains/admin/smoke-provider.js +309 -0
- package/dist/dispatch/domains/admin/smoke-provider.js.map +1 -0
- package/dist/dispatch/domains/admin.d.ts +51 -0
- package/dist/dispatch/domains/admin.d.ts.map +1 -0
- package/dist/dispatch/domains/admin.js +1163 -0
- package/dist/dispatch/domains/admin.js.map +1 -0
- package/dist/dispatch/domains/check/canon.d.ts +65 -0
- package/dist/dispatch/domains/check/canon.d.ts.map +1 -0
- package/dist/dispatch/domains/check/canon.js +193 -0
- package/dist/dispatch/domains/check/canon.js.map +1 -0
- package/dist/dispatch/domains/check.d.ts +37 -0
- package/dist/dispatch/domains/check.d.ts.map +1 -0
- package/dist/dispatch/domains/check.js +562 -0
- package/dist/dispatch/domains/check.js.map +1 -0
- package/dist/dispatch/domains/conduit.d.ts +61 -0
- package/dist/dispatch/domains/conduit.d.ts.map +1 -0
- package/dist/dispatch/domains/conduit.js +609 -0
- package/dist/dispatch/domains/conduit.js.map +1 -0
- package/dist/dispatch/domains/diagnostics.d.ts +25 -0
- package/dist/dispatch/domains/diagnostics.d.ts.map +1 -0
- package/dist/dispatch/domains/diagnostics.js +82 -0
- package/dist/dispatch/domains/diagnostics.js.map +1 -0
- package/dist/dispatch/domains/docs.d.ts +63 -0
- package/dist/dispatch/domains/docs.d.ts.map +1 -0
- package/dist/dispatch/domains/docs.js +539 -0
- package/dist/dispatch/domains/docs.js.map +1 -0
- package/dist/dispatch/domains/index.d.ts +33 -0
- package/dist/dispatch/domains/index.d.ts.map +1 -0
- package/dist/dispatch/domains/index.js +58 -0
- package/dist/dispatch/domains/index.js.map +1 -0
- package/dist/dispatch/domains/intelligence.d.ts +26 -0
- package/dist/dispatch/domains/intelligence.d.ts.map +1 -0
- package/dist/dispatch/domains/intelligence.js +154 -0
- package/dist/dispatch/domains/intelligence.js.map +1 -0
- package/dist/dispatch/domains/ivtr.d.ts +182 -0
- package/dist/dispatch/domains/ivtr.d.ts.map +1 -0
- package/dist/dispatch/domains/ivtr.js +430 -0
- package/dist/dispatch/domains/ivtr.js.map +1 -0
- package/dist/dispatch/domains/memory.d.ts +22 -0
- package/dist/dispatch/domains/memory.d.ts.map +1 -0
- package/dist/dispatch/domains/memory.js +1281 -0
- package/dist/dispatch/domains/memory.js.map +1 -0
- package/dist/dispatch/domains/nexus.d.ts +78 -0
- package/dist/dispatch/domains/nexus.d.ts.map +1 -0
- package/dist/dispatch/domains/nexus.js +938 -0
- package/dist/dispatch/domains/nexus.js.map +1 -0
- package/dist/dispatch/domains/orchestrate.d.ts +307 -0
- package/dist/dispatch/domains/orchestrate.d.ts.map +1 -0
- package/dist/dispatch/domains/orchestrate.js +986 -0
- package/dist/dispatch/domains/orchestrate.js.map +1 -0
- package/dist/dispatch/domains/pipeline.d.ts +276 -0
- package/dist/dispatch/domains/pipeline.d.ts.map +1 -0
- package/dist/dispatch/domains/pipeline.js +689 -0
- package/dist/dispatch/domains/pipeline.js.map +1 -0
- package/dist/dispatch/domains/playbook.d.ts +131 -0
- package/dist/dispatch/domains/playbook.d.ts.map +1 -0
- package/dist/dispatch/domains/playbook.js +633 -0
- package/dist/dispatch/domains/playbook.js.map +1 -0
- package/dist/dispatch/domains/release.d.ts +97 -0
- package/dist/dispatch/domains/release.d.ts.map +1 -0
- package/dist/dispatch/domains/release.js +177 -0
- package/dist/dispatch/domains/release.js.map +1 -0
- package/dist/dispatch/domains/sentient.d.ts +60 -0
- package/dist/dispatch/domains/sentient.d.ts.map +1 -0
- package/dist/dispatch/domains/sentient.js +270 -0
- package/dist/dispatch/domains/sentient.js.map +1 -0
- package/dist/dispatch/domains/session.d.ts +49 -0
- package/dist/dispatch/domains/session.d.ts.map +1 -0
- package/dist/dispatch/domains/session.js +459 -0
- package/dist/dispatch/domains/session.js.map +1 -0
- package/dist/dispatch/domains/sticky.d.ts +82 -0
- package/dist/dispatch/domains/sticky.d.ts.map +1 -0
- package/dist/dispatch/domains/sticky.js +287 -0
- package/dist/dispatch/domains/sticky.js.map +1 -0
- package/dist/dispatch/domains/tasks.d.ts +58 -0
- package/dist/dispatch/domains/tasks.d.ts.map +1 -0
- package/dist/dispatch/domains/tasks.js +497 -0
- package/dist/dispatch/domains/tasks.js.map +1 -0
- package/dist/dispatch/domains/tools.d.ts +37 -0
- package/dist/dispatch/domains/tools.d.ts.map +1 -0
- package/dist/dispatch/domains/tools.js +481 -0
- package/dist/dispatch/domains/tools.js.map +1 -0
- package/dist/dispatch/engines/_error.d.ts +114 -0
- package/dist/dispatch/engines/_error.d.ts.map +1 -0
- package/dist/dispatch/engines/_error.js +290 -0
- package/dist/dispatch/engines/_error.js.map +1 -0
- package/dist/dispatch/engines/admin-engine.d.ts +386 -0
- package/dist/dispatch/engines/admin-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/admin-engine.js +270 -0
- package/dist/dispatch/engines/admin-engine.js.map +1 -0
- package/dist/dispatch/engines/code-engine.d.ts +14 -0
- package/dist/dispatch/engines/code-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/code-engine.js +14 -0
- package/dist/dispatch/engines/code-engine.js.map +1 -0
- package/dist/dispatch/engines/codebase-map-engine.d.ts +31 -0
- package/dist/dispatch/engines/codebase-map-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/codebase-map-engine.js +43 -0
- package/dist/dispatch/engines/codebase-map-engine.js.map +1 -0
- package/dist/dispatch/engines/config-engine.d.ts +14 -0
- package/dist/dispatch/engines/config-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/config-engine.js +14 -0
- package/dist/dispatch/engines/config-engine.js.map +1 -0
- package/dist/dispatch/engines/diagnostics-engine.d.ts +13 -0
- package/dist/dispatch/engines/diagnostics-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/diagnostics-engine.js +12 -0
- package/dist/dispatch/engines/diagnostics-engine.js.map +1 -0
- package/dist/dispatch/engines/hooks-engine.d.ts +13 -0
- package/dist/dispatch/engines/hooks-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/hooks-engine.js +12 -0
- package/dist/dispatch/engines/hooks-engine.js.map +1 -0
- package/dist/dispatch/engines/init-engine.d.ts +14 -0
- package/dist/dispatch/engines/init-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/init-engine.js +14 -0
- package/dist/dispatch/engines/init-engine.js.map +1 -0
- package/dist/dispatch/engines/lifecycle-engine.d.ts +13 -0
- package/dist/dispatch/engines/lifecycle-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/lifecycle-engine.js +12 -0
- package/dist/dispatch/engines/lifecycle-engine.js.map +1 -0
- package/dist/dispatch/engines/memory-engine.d.ts +10 -0
- package/dist/dispatch/engines/memory-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/memory-engine.js +10 -0
- package/dist/dispatch/engines/memory-engine.js.map +1 -0
- package/dist/dispatch/engines/nexus-engine.d.ts +603 -0
- package/dist/dispatch/engines/nexus-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/nexus-engine.js +1438 -0
- package/dist/dispatch/engines/nexus-engine.js.map +1 -0
- package/dist/dispatch/engines/orchestrate-engine.d.ts +252 -0
- package/dist/dispatch/engines/orchestrate-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/orchestrate-engine.js +1526 -0
- package/dist/dispatch/engines/orchestrate-engine.js.map +1 -0
- package/dist/dispatch/engines/pipeline-engine.d.ts +13 -0
- package/dist/dispatch/engines/pipeline-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/pipeline-engine.js +12 -0
- package/dist/dispatch/engines/pipeline-engine.js.map +1 -0
- package/dist/dispatch/engines/release-engine.d.ts +13 -0
- package/dist/dispatch/engines/release-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/release-engine.js +13 -0
- package/dist/dispatch/engines/release-engine.js.map +1 -0
- package/dist/dispatch/engines/session-engine.d.ts +15 -0
- package/dist/dispatch/engines/session-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/session-engine.js +12 -0
- package/dist/dispatch/engines/session-engine.js.map +1 -0
- package/dist/dispatch/engines/sticky-engine.d.ts +13 -0
- package/dist/dispatch/engines/sticky-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/sticky-engine.js +12 -0
- package/dist/dispatch/engines/sticky-engine.js.map +1 -0
- package/dist/dispatch/engines/system-engine.d.ts +543 -0
- package/dist/dispatch/engines/system-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/system-engine.js +1278 -0
- package/dist/dispatch/engines/system-engine.js.map +1 -0
- package/dist/dispatch/engines/task-engine.d.ts +1161 -0
- package/dist/dispatch/engines/task-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/task-engine.js +1599 -0
- package/dist/dispatch/engines/task-engine.js.map +1 -0
- package/dist/dispatch/engines/template-parser.d.ts +85 -0
- package/dist/dispatch/engines/template-parser.d.ts.map +1 -0
- package/dist/dispatch/engines/template-parser.js +114 -0
- package/dist/dispatch/engines/template-parser.js.map +1 -0
- package/dist/dispatch/engines/tools-engine.d.ts +13 -0
- package/dist/dispatch/engines/tools-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/tools-engine.js +12 -0
- package/dist/dispatch/engines/tools-engine.js.map +1 -0
- package/dist/dispatch/engines/validate-engine.d.ts +13 -0
- package/dist/dispatch/engines/validate-engine.d.ts.map +1 -0
- package/dist/dispatch/engines/validate-engine.js +13 -0
- package/dist/dispatch/engines/validate-engine.js.map +1 -0
- package/dist/dispatch/index.d.ts +20 -0
- package/dist/dispatch/index.d.ts.map +1 -0
- package/dist/dispatch/index.js +19 -0
- package/dist/dispatch/index.js.map +1 -0
- package/dist/dispatch/lib/background-jobs.d.ts +162 -0
- package/dist/dispatch/lib/background-jobs.d.ts.map +1 -0
- package/dist/dispatch/lib/background-jobs.js +360 -0
- package/dist/dispatch/lib/background-jobs.js.map +1 -0
- package/dist/dispatch/lib/budget.d.ts +36 -0
- package/dist/dispatch/lib/budget.d.ts.map +1 -0
- package/dist/dispatch/lib/budget.js +109 -0
- package/dist/dispatch/lib/budget.js.map +1 -0
- package/dist/dispatch/lib/capability-matrix.d.ts +11 -0
- package/dist/dispatch/lib/capability-matrix.d.ts.map +1 -0
- package/dist/dispatch/lib/capability-matrix.js +10 -0
- package/dist/dispatch/lib/capability-matrix.js.map +1 -0
- package/dist/dispatch/lib/config-loader.d.ts +42 -0
- package/dist/dispatch/lib/config-loader.d.ts.map +1 -0
- package/dist/dispatch/lib/config-loader.js +218 -0
- package/dist/dispatch/lib/config-loader.js.map +1 -0
- package/dist/dispatch/lib/config.d.ts +11 -0
- package/dist/dispatch/lib/config.d.ts.map +1 -0
- package/dist/dispatch/lib/config.js +10 -0
- package/dist/dispatch/lib/config.js.map +1 -0
- package/dist/dispatch/lib/defaults.d.ts +115 -0
- package/dist/dispatch/lib/defaults.d.ts.map +1 -0
- package/dist/dispatch/lib/defaults.js +61 -0
- package/dist/dispatch/lib/defaults.js.map +1 -0
- package/dist/dispatch/lib/engine.d.ts +17 -0
- package/dist/dispatch/lib/engine.d.ts.map +1 -0
- package/dist/dispatch/lib/engine.js +36 -0
- package/dist/dispatch/lib/engine.js.map +1 -0
- package/dist/dispatch/lib/exit-codes.d.ts +35 -0
- package/dist/dispatch/lib/exit-codes.d.ts.map +1 -0
- package/dist/dispatch/lib/exit-codes.js +60 -0
- package/dist/dispatch/lib/exit-codes.js.map +1 -0
- package/dist/dispatch/lib/gateway-meta.d.ts +37 -0
- package/dist/dispatch/lib/gateway-meta.d.ts.map +1 -0
- package/dist/dispatch/lib/gateway-meta.js +50 -0
- package/dist/dispatch/lib/gateway-meta.js.map +1 -0
- package/dist/dispatch/lib/job-manager-accessor.d.ts +9 -0
- package/dist/dispatch/lib/job-manager-accessor.d.ts.map +1 -0
- package/dist/dispatch/lib/job-manager-accessor.js +13 -0
- package/dist/dispatch/lib/job-manager-accessor.js.map +1 -0
- package/dist/dispatch/lib/meta.d.ts +26 -0
- package/dist/dispatch/lib/meta.d.ts.map +1 -0
- package/dist/dispatch/lib/meta.js +37 -0
- package/dist/dispatch/lib/meta.js.map +1 -0
- package/dist/dispatch/lib/param-utils.d.ts +11 -0
- package/dist/dispatch/lib/param-utils.d.ts.map +1 -0
- package/dist/dispatch/lib/param-utils.js +10 -0
- package/dist/dispatch/lib/param-utils.js.map +1 -0
- package/dist/dispatch/lib/projections.d.ts +56 -0
- package/dist/dispatch/lib/projections.d.ts.map +1 -0
- package/dist/dispatch/lib/projections.js +65 -0
- package/dist/dispatch/lib/projections.js.map +1 -0
- package/dist/dispatch/lib/proto-envelope.d.ts +56 -0
- package/dist/dispatch/lib/proto-envelope.d.ts.map +1 -0
- package/dist/dispatch/lib/proto-envelope.js +17 -0
- package/dist/dispatch/lib/proto-envelope.js.map +1 -0
- package/dist/dispatch/lib/schema-utils.d.ts +39 -0
- package/dist/dispatch/lib/schema-utils.d.ts.map +1 -0
- package/dist/dispatch/lib/schema-utils.js +88 -0
- package/dist/dispatch/lib/schema-utils.js.map +1 -0
- package/dist/dispatch/lib/security.d.ts +11 -0
- package/dist/dispatch/lib/security.d.ts.map +1 -0
- package/dist/dispatch/lib/security.js +10 -0
- package/dist/dispatch/lib/security.js.map +1 -0
- package/dist/dispatch/middleware/audit.d.ts +23 -0
- package/dist/dispatch/middleware/audit.d.ts.map +1 -0
- package/dist/dispatch/middleware/audit.js +169 -0
- package/dist/dispatch/middleware/audit.js.map +1 -0
- package/dist/dispatch/middleware/field-filter.d.ts +25 -0
- package/dist/dispatch/middleware/field-filter.d.ts.map +1 -0
- package/dist/dispatch/middleware/field-filter.js +70 -0
- package/dist/dispatch/middleware/field-filter.js.map +1 -0
- package/dist/dispatch/middleware/pipeline.d.ts +33 -0
- package/dist/dispatch/middleware/pipeline.d.ts.map +1 -0
- package/dist/dispatch/middleware/pipeline.js +60 -0
- package/dist/dispatch/middleware/pipeline.js.map +1 -0
- package/dist/dispatch/middleware/projection.d.ts +35 -0
- package/dist/dispatch/middleware/projection.d.ts.map +1 -0
- package/dist/dispatch/middleware/projection.js +146 -0
- package/dist/dispatch/middleware/projection.js.map +1 -0
- package/dist/dispatch/middleware/protocol-enforcement.d.ts +30 -0
- package/dist/dispatch/middleware/protocol-enforcement.d.ts.map +1 -0
- package/dist/dispatch/middleware/protocol-enforcement.js +56 -0
- package/dist/dispatch/middleware/protocol-enforcement.js.map +1 -0
- package/dist/dispatch/middleware/rate-limiter.d.ts +72 -0
- package/dist/dispatch/middleware/rate-limiter.d.ts.map +1 -0
- package/dist/dispatch/middleware/rate-limiter.js +127 -0
- package/dist/dispatch/middleware/rate-limiter.js.map +1 -0
- package/dist/dispatch/middleware/sanitizer.d.ts +24 -0
- package/dist/dispatch/middleware/sanitizer.d.ts.map +1 -0
- package/dist/dispatch/middleware/sanitizer.js +56 -0
- package/dist/dispatch/middleware/sanitizer.js.map +1 -0
- package/dist/dispatch/middleware/session-resolver.d.ts +26 -0
- package/dist/dispatch/middleware/session-resolver.d.ts.map +1 -0
- package/dist/dispatch/middleware/session-resolver.js +65 -0
- package/dist/dispatch/middleware/session-resolver.js.map +1 -0
- package/dist/dispatch/middleware/telemetry.d.ts +21 -0
- package/dist/dispatch/middleware/telemetry.d.ts.map +1 -0
- package/dist/dispatch/middleware/telemetry.js +50 -0
- package/dist/dispatch/middleware/telemetry.js.map +1 -0
- package/dist/dispatch/middleware/verification-gates.d.ts +22 -0
- package/dist/dispatch/middleware/verification-gates.d.ts.map +1 -0
- package/dist/dispatch/middleware/verification-gates.js +59 -0
- package/dist/dispatch/middleware/verification-gates.js.map +1 -0
- package/dist/dispatch/registry.d.ts +91 -0
- package/dist/dispatch/registry.d.ts.map +1 -0
- package/dist/dispatch/registry.js +6430 -0
- package/dist/dispatch/registry.js.map +1 -0
- package/dist/dispatch/types.d.ts +150 -0
- package/dist/dispatch/types.d.ts.map +1 -0
- package/dist/dispatch/types.js +38 -0
- package/dist/dispatch/types.js.map +1 -0
- package/dist/migrations/2026-04-25-t991-parent-link-repair.d.ts +88 -0
- package/dist/migrations/2026-04-25-t991-parent-link-repair.d.ts.map +1 -0
- package/dist/migrations/2026-04-25-t991-parent-link-repair.js +76 -0
- package/dist/migrations/2026-04-25-t991-parent-link-repair.js.map +1 -0
- package/package.json +9 -9
- package/templates/HANDOFF-REDIRECT-STUB.md +37 -0
- package/templates/hooks/commit-msg +146 -6
|
@@ -0,0 +1,3377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI nexus command group - Cross-project NEXUS operations.
|
|
3
|
+
*
|
|
4
|
+
* Thin CLI wrappers routing through the dispatch layer.
|
|
5
|
+
* All business logic lives in src/dispatch/domains/nexus.ts.
|
|
6
|
+
*
|
|
7
|
+
* `nexus analyze` is implemented directly here because it requires
|
|
8
|
+
* `@cleocode/nexus` pipeline access and `@cleocode/core` DB access together,
|
|
9
|
+
* and routing through the dispatch layer would create awkward coupling.
|
|
10
|
+
*
|
|
11
|
+
* @task T4554, T5323, T5330, T481, T534
|
|
12
|
+
* @epic T4545
|
|
13
|
+
*/
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { generateGexf, getSymbolImpact } from '@cleocode/core/nexus';
|
|
16
|
+
import { defineCommand, showUsage } from 'citty';
|
|
17
|
+
import { dispatchFromCli, dispatchRaw } from '../../dispatch/adapters/cli.js';
|
|
18
|
+
// ── Subcommand definitions ───────────────────────────────────────────────────
|
|
19
|
+
/** cleo nexus init — initialize NEXUS directory structure and registry */
|
|
20
|
+
const initCommand = defineCommand({
|
|
21
|
+
meta: { name: 'init', description: 'Initialize NEXUS directory structure and registry' },
|
|
22
|
+
async run() {
|
|
23
|
+
await dispatchFromCli('mutate', 'nexus', 'init', {}, { command: 'nexus' });
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
/** cleo nexus register — register a project in the global registry */
|
|
27
|
+
const registerCommand = defineCommand({
|
|
28
|
+
meta: { name: 'register', description: 'Register a project in the global registry' },
|
|
29
|
+
args: {
|
|
30
|
+
path: {
|
|
31
|
+
type: 'positional',
|
|
32
|
+
description: 'Path to the project directory',
|
|
33
|
+
required: true,
|
|
34
|
+
},
|
|
35
|
+
name: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
description: 'Custom project name (default: directory name)',
|
|
38
|
+
},
|
|
39
|
+
permissions: {
|
|
40
|
+
type: 'string',
|
|
41
|
+
description: 'Permissions: read|write|execute',
|
|
42
|
+
default: 'read',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
async run({ args }) {
|
|
46
|
+
await dispatchFromCli('mutate', 'nexus', 'register', {
|
|
47
|
+
path: args.path,
|
|
48
|
+
name: args.name,
|
|
49
|
+
permission: args.permissions,
|
|
50
|
+
}, { command: 'nexus' });
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
/** cleo nexus unregister — remove a project from the registry */
|
|
54
|
+
const unregisterCommand = defineCommand({
|
|
55
|
+
meta: { name: 'unregister', description: 'Remove a project from the registry' },
|
|
56
|
+
args: {
|
|
57
|
+
nameOrHash: {
|
|
58
|
+
type: 'positional',
|
|
59
|
+
description: 'Project name or hash to unregister',
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
async run({ args }) {
|
|
64
|
+
await dispatchFromCli('mutate', 'nexus', 'unregister', { name: args.nameOrHash }, { command: 'nexus' });
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
/** cleo nexus list — list all registered projects */
|
|
68
|
+
const listCommand = defineCommand({
|
|
69
|
+
meta: { name: 'list', description: 'List all registered projects' },
|
|
70
|
+
async run() {
|
|
71
|
+
await dispatchFromCli('query', 'nexus', 'list', {}, { command: 'nexus' });
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
/** cleo nexus status — show code intelligence index freshness */
|
|
75
|
+
const statusCommand = defineCommand({
|
|
76
|
+
meta: {
|
|
77
|
+
name: 'status',
|
|
78
|
+
description: 'Show code intelligence index freshness: file count, node/relation counts, last indexed time, stale files. Falls back to NEXUS registry status if code-intelligence index is unavailable.',
|
|
79
|
+
},
|
|
80
|
+
args: {
|
|
81
|
+
path: {
|
|
82
|
+
type: 'positional',
|
|
83
|
+
description: 'Path to the project directory (default: cwd)',
|
|
84
|
+
required: false,
|
|
85
|
+
},
|
|
86
|
+
'project-id': {
|
|
87
|
+
type: 'string',
|
|
88
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
89
|
+
},
|
|
90
|
+
json: {
|
|
91
|
+
type: 'boolean',
|
|
92
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
async run({ args }) {
|
|
96
|
+
const jsonOutput = !!args.json;
|
|
97
|
+
const projectIdOverride = args['project-id'];
|
|
98
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
99
|
+
const startTime = Date.now();
|
|
100
|
+
try {
|
|
101
|
+
// SSoT-EXEMPT:status-index-stats — getIndexStats requires direct pipeline access
|
|
102
|
+
// with db handle + table refs; no dispatch op exposes this level of detail.
|
|
103
|
+
// Dispatch 'nexus.status' is used as fallback on error (see catch block).
|
|
104
|
+
const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
|
|
105
|
+
import('@cleocode/core/store/nexus-sqlite'),
|
|
106
|
+
import('@cleocode/nexus/pipeline'),
|
|
107
|
+
]);
|
|
108
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
109
|
+
const db = await getNexusDb();
|
|
110
|
+
const tables = {
|
|
111
|
+
nexusNodes: nexusSchema.nexusNodes,
|
|
112
|
+
nexusRelations: nexusSchema.nexusRelations,
|
|
113
|
+
};
|
|
114
|
+
const stats = await getIndexStats(projectId, repoPath, db, tables);
|
|
115
|
+
const durationMs = Date.now() - startTime;
|
|
116
|
+
if (jsonOutput) {
|
|
117
|
+
const envelope = {
|
|
118
|
+
success: true,
|
|
119
|
+
data: { projectId, repoPath, ...stats },
|
|
120
|
+
meta: {
|
|
121
|
+
operation: 'nexus.status',
|
|
122
|
+
duration_ms: durationMs,
|
|
123
|
+
timestamp: new Date().toISOString(),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
|
|
127
|
+
}
|
|
128
|
+
else if (!stats.indexed) {
|
|
129
|
+
process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
|
|
130
|
+
` Status: NOT INDEXED\n` +
|
|
131
|
+
` Run 'cleo nexus analyze' to build the index.\n`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const staleLabel = stats.staleFileCount < 0
|
|
135
|
+
? 'unknown'
|
|
136
|
+
: stats.staleFileCount === 0
|
|
137
|
+
? 'up to date'
|
|
138
|
+
: `${stats.staleFileCount} stale`;
|
|
139
|
+
process.stdout.write(`[nexus] Index status for: ${repoPath}\n` +
|
|
140
|
+
` Project ID: ${projectId}\n` +
|
|
141
|
+
` Nodes: ${stats.nodeCount}\n` +
|
|
142
|
+
` Relations: ${stats.relationCount}\n` +
|
|
143
|
+
` Files: ${stats.fileCount}\n` +
|
|
144
|
+
` Last indexed: ${stats.lastIndexedAt ?? 'never'}\n` +
|
|
145
|
+
` Staleness: ${staleLabel}\n`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
// Fall back to NEXUS registry status on error
|
|
150
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
151
|
+
if (jsonOutput) {
|
|
152
|
+
process.stdout.write(JSON.stringify({
|
|
153
|
+
success: false,
|
|
154
|
+
error: { code: 'E_STATUS_FAILED', message: msg },
|
|
155
|
+
meta: {
|
|
156
|
+
operation: 'nexus.status',
|
|
157
|
+
duration_ms: Date.now() - startTime,
|
|
158
|
+
timestamp: new Date().toISOString(),
|
|
159
|
+
},
|
|
160
|
+
}, null, 2) + '\n');
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
164
|
+
await dispatchFromCli('query', 'nexus', 'status', {}, { command: 'nexus' });
|
|
165
|
+
}
|
|
166
|
+
process.exitCode = 1;
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
/** cleo nexus show — show details for a registered project by name */
|
|
171
|
+
const showCommand = defineCommand({
|
|
172
|
+
meta: { name: 'show', description: 'Show details for a registered project by name' },
|
|
173
|
+
args: {
|
|
174
|
+
name: {
|
|
175
|
+
type: 'positional',
|
|
176
|
+
description: 'Project name',
|
|
177
|
+
required: true,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
async run({ args }) {
|
|
181
|
+
await dispatchFromCli('query', 'nexus', 'show', { name: args.name }, { command: 'nexus' });
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
/** cleo nexus resolve — resolve a task reference across projects */
|
|
185
|
+
const resolveCommand = defineCommand({
|
|
186
|
+
meta: {
|
|
187
|
+
name: 'resolve',
|
|
188
|
+
description: 'Resolve a task reference across projects (project:T### or T###)',
|
|
189
|
+
},
|
|
190
|
+
args: {
|
|
191
|
+
taskRef: {
|
|
192
|
+
type: 'positional',
|
|
193
|
+
description: 'Task reference to resolve',
|
|
194
|
+
required: true,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
async run({ args }) {
|
|
198
|
+
await dispatchFromCli('query', 'nexus', 'resolve', { query: args.taskRef }, { command: 'nexus' });
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
/** cleo nexus discover — find related tasks across projects */
|
|
202
|
+
const discoverCommand = defineCommand({
|
|
203
|
+
meta: { name: 'discover', description: 'Find related tasks across projects' },
|
|
204
|
+
args: {
|
|
205
|
+
taskQuery: {
|
|
206
|
+
type: 'positional',
|
|
207
|
+
description: 'Task query string',
|
|
208
|
+
required: true,
|
|
209
|
+
},
|
|
210
|
+
method: {
|
|
211
|
+
type: 'string',
|
|
212
|
+
description: 'Discovery method: labels|description|files|auto',
|
|
213
|
+
default: 'auto',
|
|
214
|
+
},
|
|
215
|
+
limit: {
|
|
216
|
+
type: 'string',
|
|
217
|
+
description: 'Max results',
|
|
218
|
+
default: '10',
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
async run({ args }) {
|
|
222
|
+
await dispatchFromCli('query', 'nexus', 'discover', {
|
|
223
|
+
query: args.taskQuery,
|
|
224
|
+
method: args.method,
|
|
225
|
+
limit: parseInt(args.limit, 10),
|
|
226
|
+
}, { command: 'nexus' });
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
/**
|
|
230
|
+
* cleo nexus augment — Symbol context augmentation for PreToolUse hooks.
|
|
231
|
+
*
|
|
232
|
+
* BM25-only search against nexus_nodes for pattern, returns top N symbols
|
|
233
|
+
* with callers/callees/community metadata as plain text suitable for hook injection.
|
|
234
|
+
*
|
|
235
|
+
* @task T1061
|
|
236
|
+
* @epic T1042
|
|
237
|
+
*/
|
|
238
|
+
const augmentCommand = defineCommand({
|
|
239
|
+
meta: {
|
|
240
|
+
name: 'augment',
|
|
241
|
+
description: 'Augment symbol pattern with code context (for PreToolUse hooks)',
|
|
242
|
+
},
|
|
243
|
+
args: {
|
|
244
|
+
pattern: {
|
|
245
|
+
type: 'positional',
|
|
246
|
+
description: 'Symbol name or file pattern to search',
|
|
247
|
+
required: true,
|
|
248
|
+
},
|
|
249
|
+
limit: {
|
|
250
|
+
type: 'string',
|
|
251
|
+
description: 'Max results to return (default: 5)',
|
|
252
|
+
default: '5',
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
async run({ args }) {
|
|
256
|
+
const pattern = args.pattern;
|
|
257
|
+
const limit = parseInt(args.limit, 10) || 5;
|
|
258
|
+
await dispatchFromCli('query', 'nexus', 'augment', {
|
|
259
|
+
pattern,
|
|
260
|
+
limit,
|
|
261
|
+
}, { command: 'nexus' });
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
/**
|
|
265
|
+
* cleo nexus setup — Install PreToolUse hook augmenter
|
|
266
|
+
*
|
|
267
|
+
* Writes ~/.cleo/hooks/nexus-augment.sh and registers it in CAAMP config.
|
|
268
|
+
*
|
|
269
|
+
* @task T1061
|
|
270
|
+
* @epic T1042
|
|
271
|
+
*/
|
|
272
|
+
const setupCommand = defineCommand({
|
|
273
|
+
meta: {
|
|
274
|
+
name: 'setup',
|
|
275
|
+
description: 'Install Nexus PreToolUse hook augmenter',
|
|
276
|
+
},
|
|
277
|
+
args: {},
|
|
278
|
+
async run() {
|
|
279
|
+
try {
|
|
280
|
+
// SSoT-EXEMPT:cli-install — installs filesystem hook, not a domain operation.
|
|
281
|
+
// Hook installation writes shell scripts to disk and cannot be a LAFS dispatch op.
|
|
282
|
+
const { homedir } = await import('node:os');
|
|
283
|
+
const { installNexusAugmentHook } = await import('@cleocode/core/internal');
|
|
284
|
+
const homeDir = homedir();
|
|
285
|
+
installNexusAugmentHook(homeDir);
|
|
286
|
+
process.stdout.write(`[nexus] Installed PreToolUse hook at ${homeDir}/.cleo/hooks/nexus-augment.sh\n`);
|
|
287
|
+
process.stdout.write(`[nexus] Hook will inject symbol context into Grep/Glob/Read tool calls\n`);
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
291
|
+
process.stderr.write(`[nexus setup] Error: ${msg}\n`);
|
|
292
|
+
process.exitCode = 1;
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
/** cleo nexus search — search tasks across projects by pattern */
|
|
297
|
+
const searchCommand = defineCommand({
|
|
298
|
+
meta: { name: 'search', description: 'Search tasks across projects by pattern' },
|
|
299
|
+
args: {
|
|
300
|
+
pattern: {
|
|
301
|
+
type: 'positional',
|
|
302
|
+
description: 'Search pattern',
|
|
303
|
+
required: true,
|
|
304
|
+
},
|
|
305
|
+
project: {
|
|
306
|
+
type: 'string',
|
|
307
|
+
description: 'Limit search to specific project',
|
|
308
|
+
},
|
|
309
|
+
limit: {
|
|
310
|
+
type: 'string',
|
|
311
|
+
description: 'Max results',
|
|
312
|
+
default: '20',
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
async run({ args }) {
|
|
316
|
+
await dispatchFromCli('query', 'nexus', 'search', {
|
|
317
|
+
pattern: args.pattern,
|
|
318
|
+
project: args.project,
|
|
319
|
+
limit: parseInt(args.limit, 10),
|
|
320
|
+
}, { command: 'nexus' });
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
/** cleo nexus deps — show cross-project dependencies */
|
|
324
|
+
const depsCommand = defineCommand({
|
|
325
|
+
meta: { name: 'deps', description: 'Show cross-project dependencies' },
|
|
326
|
+
args: {
|
|
327
|
+
taskQuery: {
|
|
328
|
+
type: 'positional',
|
|
329
|
+
description: 'Task query string',
|
|
330
|
+
required: true,
|
|
331
|
+
},
|
|
332
|
+
reverse: {
|
|
333
|
+
type: 'boolean',
|
|
334
|
+
description: 'Show reverse dependencies (what depends on this)',
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
async run({ args }) {
|
|
338
|
+
await dispatchFromCli('query', 'nexus', 'deps', {
|
|
339
|
+
query: args.taskQuery,
|
|
340
|
+
direction: args.reverse ? 'reverse' : 'forward',
|
|
341
|
+
}, { command: 'nexus' });
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
/** cleo nexus critical-path — show global critical path across all registered projects */
|
|
345
|
+
const criticalPathCommand = defineCommand({
|
|
346
|
+
meta: {
|
|
347
|
+
name: 'critical-path',
|
|
348
|
+
description: 'Show global critical path across all registered projects',
|
|
349
|
+
},
|
|
350
|
+
async run() {
|
|
351
|
+
await dispatchFromCli('query', 'nexus', 'path.show', {}, { command: 'nexus' });
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
/** cleo nexus blocking — show blocking impact analysis for a task */
|
|
355
|
+
const blockingCommand = defineCommand({
|
|
356
|
+
meta: { name: 'blocking', description: 'Show blocking impact analysis for a task' },
|
|
357
|
+
args: {
|
|
358
|
+
taskQuery: {
|
|
359
|
+
type: 'positional',
|
|
360
|
+
description: 'Task query string',
|
|
361
|
+
required: true,
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
async run({ args }) {
|
|
365
|
+
await dispatchFromCli('query', 'nexus', 'blockers.show', { query: args.taskQuery }, { command: 'nexus' });
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
/** cleo nexus orphans — detect broken cross-project dependency references */
|
|
369
|
+
const orphansCommand = defineCommand({
|
|
370
|
+
meta: { name: 'orphans', description: 'Detect broken cross-project dependency references' },
|
|
371
|
+
async run() {
|
|
372
|
+
await dispatchFromCli('query', 'nexus', 'orphans.list', {}, { command: 'nexus' });
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
/** cleo nexus sync — sync project metadata (task count, labels) */
|
|
376
|
+
const syncCommand = defineCommand({
|
|
377
|
+
meta: { name: 'sync', description: 'Sync project metadata (task count, labels)' },
|
|
378
|
+
args: {
|
|
379
|
+
project: {
|
|
380
|
+
type: 'positional',
|
|
381
|
+
description: 'Project name to sync (default: all)',
|
|
382
|
+
required: false,
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
async run({ args }) {
|
|
386
|
+
if (args.project) {
|
|
387
|
+
await dispatchFromCli('mutate', 'nexus', 'sync', { name: args.project }, { command: 'nexus' });
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
await dispatchFromCli('mutate', 'nexus', 'sync', {}, { command: 'nexus' });
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
/** cleo nexus reconcile — reconcile current project with NEXUS registry */
|
|
395
|
+
const reconcileCommand = defineCommand({
|
|
396
|
+
meta: {
|
|
397
|
+
name: 'reconcile',
|
|
398
|
+
description: 'Reconcile current project with NEXUS registry (auto-register if new, update path if moved)',
|
|
399
|
+
},
|
|
400
|
+
args: {
|
|
401
|
+
path: {
|
|
402
|
+
type: 'string',
|
|
403
|
+
description: 'Project path (default: current directory)',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
async run({ args }) {
|
|
407
|
+
await dispatchFromCli('mutate', 'nexus', 'reconcile', { projectRoot: args.path }, { command: 'nexus' });
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
/** cleo nexus graph — show full dependency graph across all registered projects */
|
|
411
|
+
const graphCommand = defineCommand({
|
|
412
|
+
meta: { name: 'graph', description: 'Show full dependency graph across all registered projects' },
|
|
413
|
+
async run() {
|
|
414
|
+
await dispatchFromCli('query', 'nexus', 'graph', {}, { command: 'nexus' });
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
/** cleo nexus share-status — show multi-contributor sharing status */
|
|
418
|
+
const shareStatusCommand = defineCommand({
|
|
419
|
+
meta: {
|
|
420
|
+
name: 'share-status',
|
|
421
|
+
description: 'Show multi-contributor sharing status for the current project',
|
|
422
|
+
},
|
|
423
|
+
async run() {
|
|
424
|
+
await dispatchFromCli('query', 'nexus', 'share.status', {}, { command: 'nexus' });
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
/** cleo nexus transfer-preview — preview a task transfer between projects */
|
|
428
|
+
const transferPreviewCommand = defineCommand({
|
|
429
|
+
meta: {
|
|
430
|
+
name: 'transfer-preview',
|
|
431
|
+
description: 'Preview a task transfer between projects (dry-run, no changes made)',
|
|
432
|
+
},
|
|
433
|
+
args: {
|
|
434
|
+
taskIds: {
|
|
435
|
+
type: 'positional',
|
|
436
|
+
description: 'Task IDs to preview transfer for',
|
|
437
|
+
required: true,
|
|
438
|
+
},
|
|
439
|
+
from: {
|
|
440
|
+
type: 'string',
|
|
441
|
+
description: 'Source project name',
|
|
442
|
+
required: true,
|
|
443
|
+
},
|
|
444
|
+
to: {
|
|
445
|
+
type: 'string',
|
|
446
|
+
description: 'Target project name',
|
|
447
|
+
required: true,
|
|
448
|
+
},
|
|
449
|
+
mode: {
|
|
450
|
+
type: 'string',
|
|
451
|
+
description: 'Transfer mode: copy|move',
|
|
452
|
+
default: 'copy',
|
|
453
|
+
},
|
|
454
|
+
scope: {
|
|
455
|
+
type: 'string',
|
|
456
|
+
description: 'Transfer scope: single|subtree',
|
|
457
|
+
default: 'subtree',
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
async run({ args }) {
|
|
461
|
+
await dispatchFromCli('query', 'nexus', 'transfer.preview', {
|
|
462
|
+
taskIds: args.taskIds.split(',').map((s) => s.trim()),
|
|
463
|
+
sourceProject: args.from,
|
|
464
|
+
targetProject: args.to,
|
|
465
|
+
mode: args.mode,
|
|
466
|
+
scope: args.scope,
|
|
467
|
+
}, { command: 'nexus' });
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
/** cleo nexus transfer — transfer tasks from one project to another */
|
|
471
|
+
const transferCommand = defineCommand({
|
|
472
|
+
meta: { name: 'transfer', description: 'Transfer tasks from one project to another' },
|
|
473
|
+
args: {
|
|
474
|
+
taskIds: {
|
|
475
|
+
type: 'positional',
|
|
476
|
+
description: 'Task IDs to transfer',
|
|
477
|
+
required: true,
|
|
478
|
+
},
|
|
479
|
+
from: {
|
|
480
|
+
type: 'string',
|
|
481
|
+
description: 'Source project name',
|
|
482
|
+
required: true,
|
|
483
|
+
},
|
|
484
|
+
to: {
|
|
485
|
+
type: 'string',
|
|
486
|
+
description: 'Target project name',
|
|
487
|
+
required: true,
|
|
488
|
+
},
|
|
489
|
+
mode: {
|
|
490
|
+
type: 'string',
|
|
491
|
+
description: 'Transfer mode: copy|move',
|
|
492
|
+
default: 'copy',
|
|
493
|
+
},
|
|
494
|
+
scope: {
|
|
495
|
+
type: 'string',
|
|
496
|
+
description: 'Transfer scope: single|subtree',
|
|
497
|
+
default: 'subtree',
|
|
498
|
+
},
|
|
499
|
+
'on-conflict': {
|
|
500
|
+
type: 'string',
|
|
501
|
+
description: 'Conflict strategy: rename|skip|duplicate|fail',
|
|
502
|
+
default: 'rename',
|
|
503
|
+
},
|
|
504
|
+
'transfer-brain': {
|
|
505
|
+
type: 'boolean',
|
|
506
|
+
description: 'Also transfer associated brain memory entries',
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
async run({ args }) {
|
|
510
|
+
await dispatchFromCli('mutate', 'nexus', 'transfer', {
|
|
511
|
+
taskIds: args.taskIds.split(',').map((s) => s.trim()),
|
|
512
|
+
sourceProject: args.from,
|
|
513
|
+
targetProject: args.to,
|
|
514
|
+
mode: args.mode,
|
|
515
|
+
scope: args.scope,
|
|
516
|
+
onConflict: args['on-conflict'],
|
|
517
|
+
transferBrain: args['transfer-brain'],
|
|
518
|
+
}, { command: 'nexus' });
|
|
519
|
+
},
|
|
520
|
+
});
|
|
521
|
+
/** cleo nexus permission set — set permission level for a registered project */
|
|
522
|
+
const permissionSetCommand = defineCommand({
|
|
523
|
+
meta: {
|
|
524
|
+
name: 'set',
|
|
525
|
+
description: 'Set permission level for a registered project (read|write|execute)',
|
|
526
|
+
},
|
|
527
|
+
args: {
|
|
528
|
+
name: {
|
|
529
|
+
type: 'positional',
|
|
530
|
+
description: 'Project name',
|
|
531
|
+
required: true,
|
|
532
|
+
},
|
|
533
|
+
level: {
|
|
534
|
+
type: 'positional',
|
|
535
|
+
description: 'Permission level: read|write|execute',
|
|
536
|
+
required: true,
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
async run({ args }) {
|
|
540
|
+
await dispatchFromCli('mutate', 'nexus', 'permission.set', { name: args.name, level: args.level }, { command: 'nexus' });
|
|
541
|
+
},
|
|
542
|
+
});
|
|
543
|
+
/** cleo nexus permission — manage permissions for registered projects */
|
|
544
|
+
const permissionCommand = defineCommand({
|
|
545
|
+
meta: { name: 'permission', description: 'Manage permissions for registered projects' },
|
|
546
|
+
subCommands: {
|
|
547
|
+
set: permissionSetCommand,
|
|
548
|
+
},
|
|
549
|
+
});
|
|
550
|
+
/** cleo nexus share export — export a snapshot of current project state */
|
|
551
|
+
const shareExportCommand = defineCommand({
|
|
552
|
+
meta: { name: 'export', description: 'Export a snapshot of current project state for sharing' },
|
|
553
|
+
args: {
|
|
554
|
+
output: {
|
|
555
|
+
type: 'string',
|
|
556
|
+
description: 'Output file path (default: auto-generated in current directory)',
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
async run({ args }) {
|
|
560
|
+
await dispatchFromCli('mutate', 'nexus', 'share.snapshot.export', { outputPath: args.output }, { command: 'nexus' });
|
|
561
|
+
},
|
|
562
|
+
});
|
|
563
|
+
/** cleo nexus share import — import a shared project snapshot */
|
|
564
|
+
const shareImportCommand = defineCommand({
|
|
565
|
+
meta: { name: 'import', description: 'Import a shared project snapshot' },
|
|
566
|
+
args: {
|
|
567
|
+
file: {
|
|
568
|
+
type: 'positional',
|
|
569
|
+
description: 'Path to snapshot file',
|
|
570
|
+
required: true,
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
async run({ args }) {
|
|
574
|
+
await dispatchFromCli('mutate', 'nexus', 'share.snapshot.import', { inputPath: args.file }, { command: 'nexus' });
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
/** cleo nexus share — multi-contributor sharing operations */
|
|
578
|
+
const shareCommand = defineCommand({
|
|
579
|
+
meta: { name: 'share', description: 'Multi-contributor sharing operations' },
|
|
580
|
+
subCommands: {
|
|
581
|
+
export: shareExportCommand,
|
|
582
|
+
import: shareImportCommand,
|
|
583
|
+
},
|
|
584
|
+
});
|
|
585
|
+
/** cleo nexus clusters — list all detected communities from the last analysis */
|
|
586
|
+
const clustersCommand = defineCommand({
|
|
587
|
+
meta: {
|
|
588
|
+
name: 'clusters',
|
|
589
|
+
description: 'List all detected communities (Louvain clusters) from the last analysis',
|
|
590
|
+
},
|
|
591
|
+
args: {
|
|
592
|
+
path: {
|
|
593
|
+
type: 'positional',
|
|
594
|
+
description: 'Path to project directory (default: cwd)',
|
|
595
|
+
required: false,
|
|
596
|
+
},
|
|
597
|
+
json: {
|
|
598
|
+
type: 'boolean',
|
|
599
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
600
|
+
},
|
|
601
|
+
'project-id': {
|
|
602
|
+
type: 'string',
|
|
603
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
async run({ args }) {
|
|
607
|
+
const startTime = Date.now();
|
|
608
|
+
const jsonOutput = !!args.json;
|
|
609
|
+
const projectIdOverride = args['project-id'];
|
|
610
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
611
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
612
|
+
const response = await dispatchRaw('query', 'nexus', 'clusters', { projectId, repoPath });
|
|
613
|
+
const durationMs = Date.now() - startTime;
|
|
614
|
+
if (!response.success) {
|
|
615
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
616
|
+
if (jsonOutput) {
|
|
617
|
+
process.stdout.write(JSON.stringify({
|
|
618
|
+
success: false,
|
|
619
|
+
error: { code: response.error?.code ?? 'E_CLUSTERS_FAILED', message: msg },
|
|
620
|
+
meta: {
|
|
621
|
+
operation: 'nexus.clusters',
|
|
622
|
+
duration_ms: durationMs,
|
|
623
|
+
timestamp: new Date().toISOString(),
|
|
624
|
+
},
|
|
625
|
+
}, null, 2) + '\n');
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
629
|
+
}
|
|
630
|
+
process.exitCode = 1;
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
const result = response.data;
|
|
634
|
+
if (jsonOutput) {
|
|
635
|
+
process.stdout.write(JSON.stringify({
|
|
636
|
+
success: true,
|
|
637
|
+
data: result,
|
|
638
|
+
meta: {
|
|
639
|
+
operation: 'nexus.clusters',
|
|
640
|
+
duration_ms: durationMs,
|
|
641
|
+
timestamp: new Date().toISOString(),
|
|
642
|
+
},
|
|
643
|
+
}, null, 2) + '\n');
|
|
644
|
+
}
|
|
645
|
+
else if (result.communities.length === 0) {
|
|
646
|
+
process.stdout.write(`[nexus] No communities found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
process.stdout.write(`[nexus] Communities for project ${projectId} (${result.communities.length} total):\n`);
|
|
650
|
+
for (const c of result.communities) {
|
|
651
|
+
const cohesion = typeof c.cohesion === 'number' ? c.cohesion.toFixed(3) : '0.000';
|
|
652
|
+
process.stdout.write(` ${String(c.id).padEnd(16)} label=${String(c.label ?? '').padEnd(24)} symbols=${String(c.symbolCount).padStart(5)} cohesion=${cohesion}\n`);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
},
|
|
656
|
+
});
|
|
657
|
+
/** cleo nexus flows — list all detected execution flows from the last analysis */
|
|
658
|
+
const flowsCommand = defineCommand({
|
|
659
|
+
meta: {
|
|
660
|
+
name: 'flows',
|
|
661
|
+
description: 'List all detected execution flows (processes) from the last analysis',
|
|
662
|
+
},
|
|
663
|
+
args: {
|
|
664
|
+
path: {
|
|
665
|
+
type: 'positional',
|
|
666
|
+
description: 'Path to project directory (default: cwd)',
|
|
667
|
+
required: false,
|
|
668
|
+
},
|
|
669
|
+
json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
|
|
670
|
+
'project-id': {
|
|
671
|
+
type: 'string',
|
|
672
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
673
|
+
},
|
|
674
|
+
},
|
|
675
|
+
async run({ args }) {
|
|
676
|
+
const startTime = Date.now();
|
|
677
|
+
const jsonOutput = !!args.json;
|
|
678
|
+
const projectIdOverride = args['project-id'];
|
|
679
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
680
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
681
|
+
const response = await dispatchRaw('query', 'nexus', 'flows', { projectId, repoPath });
|
|
682
|
+
const durationMs = Date.now() - startTime;
|
|
683
|
+
if (!response.success) {
|
|
684
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
685
|
+
if (jsonOutput) {
|
|
686
|
+
process.stdout.write(JSON.stringify({
|
|
687
|
+
success: false,
|
|
688
|
+
error: { code: response.error?.code ?? 'E_FLOWS_FAILED', message: msg },
|
|
689
|
+
meta: {
|
|
690
|
+
operation: 'nexus.flows',
|
|
691
|
+
duration_ms: durationMs,
|
|
692
|
+
timestamp: new Date().toISOString(),
|
|
693
|
+
},
|
|
694
|
+
}, null, 2) + '\n');
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
698
|
+
}
|
|
699
|
+
process.exitCode = 1;
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const result = response.data;
|
|
703
|
+
if (jsonOutput) {
|
|
704
|
+
process.stdout.write(JSON.stringify({
|
|
705
|
+
success: true,
|
|
706
|
+
data: result,
|
|
707
|
+
meta: {
|
|
708
|
+
operation: 'nexus.flows',
|
|
709
|
+
duration_ms: durationMs,
|
|
710
|
+
timestamp: new Date().toISOString(),
|
|
711
|
+
},
|
|
712
|
+
}, null, 2) + '\n');
|
|
713
|
+
}
|
|
714
|
+
else if (result.flows.length === 0) {
|
|
715
|
+
process.stdout.write(`[nexus] No execution flows found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
process.stdout.write(`[nexus] Execution flows for project ${projectId} (${result.flows.length} total):\n`);
|
|
719
|
+
for (const p of result.flows) {
|
|
720
|
+
const processType = p.processType.replace('_community', '');
|
|
721
|
+
process.stdout.write(` ${String(p.id).padEnd(30)} steps=${String(p.stepCount).padStart(3)} type=${processType.padEnd(12)} ${String(p.label ?? '')}\n`);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
});
|
|
726
|
+
/** cleo nexus context — show callers, callees, community membership, and process participation */
|
|
727
|
+
const contextCommand = defineCommand({
|
|
728
|
+
meta: {
|
|
729
|
+
name: 'context',
|
|
730
|
+
description: 'Show callers, callees, community membership, and process participation for a code symbol',
|
|
731
|
+
},
|
|
732
|
+
args: {
|
|
733
|
+
symbol: { type: 'positional', description: 'Symbol name to look up', required: true },
|
|
734
|
+
json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
|
|
735
|
+
'project-id': {
|
|
736
|
+
type: 'string',
|
|
737
|
+
description: 'Override the project ID (default: auto-detected from cwd)',
|
|
738
|
+
},
|
|
739
|
+
limit: { type: 'string', description: 'Max callers/callees to show per side', default: '20' },
|
|
740
|
+
content: { type: 'boolean', description: 'Append source code content for the symbol' },
|
|
741
|
+
},
|
|
742
|
+
async run({ args }) {
|
|
743
|
+
const startTime = Date.now();
|
|
744
|
+
const jsonOutput = !!args.json;
|
|
745
|
+
const projectIdOverride = args['project-id'];
|
|
746
|
+
const repoPath = process.cwd();
|
|
747
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
748
|
+
const limit = parseInt(args.limit, 10);
|
|
749
|
+
const symbolName = args.symbol;
|
|
750
|
+
const showContent = !!args.content;
|
|
751
|
+
const response = await dispatchRaw('query', 'nexus', 'context', {
|
|
752
|
+
symbol: symbolName,
|
|
753
|
+
projectId,
|
|
754
|
+
limit,
|
|
755
|
+
content: showContent,
|
|
756
|
+
});
|
|
757
|
+
const durationMs = Date.now() - startTime;
|
|
758
|
+
if (!response.success) {
|
|
759
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
760
|
+
if (jsonOutput) {
|
|
761
|
+
process.stdout.write(JSON.stringify({
|
|
762
|
+
success: false,
|
|
763
|
+
error: { code: response.error?.code ?? 'E_CONTEXT_FAILED', message: msg },
|
|
764
|
+
meta: {
|
|
765
|
+
operation: 'nexus.context',
|
|
766
|
+
duration_ms: durationMs,
|
|
767
|
+
timestamp: new Date().toISOString(),
|
|
768
|
+
},
|
|
769
|
+
}, null, 2) + '\n');
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
773
|
+
}
|
|
774
|
+
process.exitCode = 1;
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
const result = response.data;
|
|
778
|
+
if (result.matchCount === 0) {
|
|
779
|
+
if (jsonOutput) {
|
|
780
|
+
process.stdout.write(JSON.stringify({
|
|
781
|
+
success: false,
|
|
782
|
+
error: {
|
|
783
|
+
code: 'E_NOT_FOUND',
|
|
784
|
+
message: `No symbol found matching '${symbolName}' in project ${projectId}`,
|
|
785
|
+
},
|
|
786
|
+
meta: {
|
|
787
|
+
operation: 'nexus.context',
|
|
788
|
+
duration_ms: durationMs,
|
|
789
|
+
timestamp: new Date().toISOString(),
|
|
790
|
+
},
|
|
791
|
+
}, null, 2) + '\n');
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n Run 'cleo nexus analyze' first, or check the symbol name.\n`);
|
|
795
|
+
}
|
|
796
|
+
process.exitCode = 4;
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (jsonOutput) {
|
|
800
|
+
process.stdout.write(JSON.stringify({
|
|
801
|
+
success: true,
|
|
802
|
+
data: result,
|
|
803
|
+
meta: {
|
|
804
|
+
operation: 'nexus.context',
|
|
805
|
+
duration_ms: durationMs,
|
|
806
|
+
timestamp: new Date().toISOString(),
|
|
807
|
+
},
|
|
808
|
+
}, null, 2) + '\n');
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
process.stdout.write(`[nexus] Context for symbol '${symbolName}' (${result.matchCount} match${result.matchCount !== 1 ? 'es' : ''}):\n`);
|
|
812
|
+
for (const r of result.results) {
|
|
813
|
+
process.stdout.write(`\n Symbol: ${String(r.name)} (${String(r.kind)})\n File: ${r.filePath ? String(r.filePath) : 'n/a'}${r.startLine ? `:${String(r.startLine)}` : ''}\n` +
|
|
814
|
+
(r.docSummary ? ` Doc: ${String(r.docSummary)}\n` : '') +
|
|
815
|
+
(r.community ? ` Community: ${String(r.community.label ?? r.community.id)}\n` : '') +
|
|
816
|
+
` Callers (${r.callers.length}): ${r.callers.length === 0 ? 'none' : r.callers.map((c) => `${c.name}[${c.kind}]`).join(', ')}\n` +
|
|
817
|
+
` Callees (${r.callees.length}): ${r.callees.length === 0 ? 'none' : r.callees.map((c) => `${c.name}[${c.kind}]`).join(', ')}\n` +
|
|
818
|
+
(r.processes.length > 0
|
|
819
|
+
? ` Processes: ${r.processes.map((p) => `${String(p.label)}(${p.role})`).join(', ')}\n`
|
|
820
|
+
: ''));
|
|
821
|
+
if (r.source?.source) {
|
|
822
|
+
const ext = String(r.filePath).split('.').pop() ?? 'txt';
|
|
823
|
+
process.stdout.write(`\n Source (lines ${r.source.startLine}-${r.source.endLine}):\n \`\`\`${ext}\n${r.source.source
|
|
824
|
+
.split('\n')
|
|
825
|
+
.map((line) => ` ${line}`)
|
|
826
|
+
.join('\n')}\n \`\`\`\n`);
|
|
827
|
+
}
|
|
828
|
+
else if (r.source?.errors?.length) {
|
|
829
|
+
process.stdout.write(`\n [warning] Could not retrieve source: ${r.source.errors[0]}\n`);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
if (result.matchCount > 5) {
|
|
833
|
+
process.stdout.write(`\n (Showing 5 of ${result.matchCount} matches — use --json for full list)\n`);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
});
|
|
838
|
+
/** cleo nexus impact — show blast radius for a code symbol */
|
|
839
|
+
const impactCommand = defineCommand({
|
|
840
|
+
meta: {
|
|
841
|
+
name: 'impact',
|
|
842
|
+
description: 'Show blast radius for a code symbol — direct callers (d=1), indirect callers (d=2), transitive (d=3)',
|
|
843
|
+
},
|
|
844
|
+
args: {
|
|
845
|
+
symbol: { type: 'positional', description: 'Symbol name to analyze', required: true },
|
|
846
|
+
json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
|
|
847
|
+
'project-id': {
|
|
848
|
+
type: 'string',
|
|
849
|
+
description: 'Override the project ID (default: auto-detected from cwd)',
|
|
850
|
+
},
|
|
851
|
+
depth: { type: 'string', description: 'Maximum traversal depth (default: 3)', default: '3' },
|
|
852
|
+
why: { type: 'boolean', description: 'Append reasons[] path-strings for each affected symbol' },
|
|
853
|
+
},
|
|
854
|
+
async run({ args }) {
|
|
855
|
+
const startTime = Date.now();
|
|
856
|
+
const jsonOutput = !!args.json;
|
|
857
|
+
const whyFlag = !!args.why;
|
|
858
|
+
const projectIdOverride = args['project-id'];
|
|
859
|
+
const repoPath = process.cwd();
|
|
860
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
861
|
+
const maxDepth = Math.min(parseInt(args.depth, 10), 5);
|
|
862
|
+
const symbolName = args.symbol;
|
|
863
|
+
try {
|
|
864
|
+
// SSoT-EXEMPT:shape-mismatch — core NexusImpactResult (targetName/impactByDepth)
|
|
865
|
+
// differs from contracts NexusImpactResult (targetNodeId/affected); routing through
|
|
866
|
+
// dispatch.impact would require changing the output format. Tracked in T1510.
|
|
867
|
+
const result = await getSymbolImpact(symbolName, projectId, repoPath, {
|
|
868
|
+
maxDepth,
|
|
869
|
+
why: whyFlag,
|
|
870
|
+
});
|
|
871
|
+
const durationMs = Date.now() - startTime;
|
|
872
|
+
if (jsonOutput) {
|
|
873
|
+
process.stdout.write(JSON.stringify({
|
|
874
|
+
success: true,
|
|
875
|
+
data: result,
|
|
876
|
+
meta: {
|
|
877
|
+
operation: 'nexus.impact',
|
|
878
|
+
duration_ms: durationMs,
|
|
879
|
+
timestamp: new Date().toISOString(),
|
|
880
|
+
},
|
|
881
|
+
}, null, 2) + '\n');
|
|
882
|
+
}
|
|
883
|
+
else {
|
|
884
|
+
process.stdout.write(`[nexus] Impact analysis for '${symbolName}'\n Target: ${String(result.targetName)} (${String(result.targetKind)})\n File: ${result.targetFilePath ? String(result.targetFilePath) : 'n/a'}\n Risk: ${result.riskLevel} (${result.totalImpactedNodes} impacted node${result.totalImpactedNodes !== 1 ? 's' : ''})\n`);
|
|
885
|
+
if (result.totalImpactedNodes === 0) {
|
|
886
|
+
process.stdout.write(' No callers found — safe to modify.\n');
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
for (let i = 0; i < result.impactByDepth.length; i++) {
|
|
890
|
+
const layer = result.impactByDepth[i];
|
|
891
|
+
if (!layer || layer.nodes.length === 0)
|
|
892
|
+
continue;
|
|
893
|
+
const label = i === 0 ? 'WILL BREAK' : i === 1 ? 'LIKELY AFFECTED' : 'MAY NEED TESTING';
|
|
894
|
+
process.stdout.write(`\n d=${i + 1} ${label} (${layer.nodes.length}):\n`);
|
|
895
|
+
for (const node of layer.nodes.slice(0, 15)) {
|
|
896
|
+
process.stdout.write(` ${String(node.name).padEnd(36)} ${String(node.kind).padEnd(12)} ${node.filePath ?? ''}\n`);
|
|
897
|
+
if (whyFlag && node.reasons.length > 0) {
|
|
898
|
+
for (const reason of node.reasons) {
|
|
899
|
+
process.stdout.write(` why: ${reason}\n`);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (layer.nodes.length > 15) {
|
|
904
|
+
process.stdout.write(` ... and ${layer.nodes.length - 15} more\n`);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
catch (err) {
|
|
911
|
+
const code = err instanceof Error && 'code' in err ? err.code : undefined;
|
|
912
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
913
|
+
const durationMs = Date.now() - startTime;
|
|
914
|
+
if (code === 'E_NOT_FOUND') {
|
|
915
|
+
if (jsonOutput) {
|
|
916
|
+
process.stdout.write(JSON.stringify({
|
|
917
|
+
success: false,
|
|
918
|
+
error: { code: 'E_NOT_FOUND', message: msg },
|
|
919
|
+
meta: {
|
|
920
|
+
operation: 'nexus.impact',
|
|
921
|
+
duration_ms: durationMs,
|
|
922
|
+
timestamp: new Date().toISOString(),
|
|
923
|
+
},
|
|
924
|
+
}, null, 2) + '\n');
|
|
925
|
+
}
|
|
926
|
+
else {
|
|
927
|
+
process.stdout.write(`[nexus] No symbol found matching '${symbolName}'.\n Run 'cleo nexus analyze' first, or check the symbol name.\n`);
|
|
928
|
+
}
|
|
929
|
+
process.exitCode = 4;
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
932
|
+
if (jsonOutput) {
|
|
933
|
+
process.stdout.write(JSON.stringify({
|
|
934
|
+
success: false,
|
|
935
|
+
error: { code: 'E_IMPACT_FAILED', message: msg },
|
|
936
|
+
meta: {
|
|
937
|
+
operation: 'nexus.impact',
|
|
938
|
+
duration_ms: durationMs,
|
|
939
|
+
timestamp: new Date().toISOString(),
|
|
940
|
+
},
|
|
941
|
+
}, null, 2) + '\n');
|
|
942
|
+
}
|
|
943
|
+
else {
|
|
944
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
945
|
+
}
|
|
946
|
+
process.exitCode = 1;
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
});
|
|
950
|
+
/** cleo nexus analyze — run code intelligence pipeline on a repository directory */
|
|
951
|
+
const analyzeCommand = defineCommand({
|
|
952
|
+
meta: {
|
|
953
|
+
name: 'analyze',
|
|
954
|
+
description: 'Run code intelligence pipeline on a repository directory',
|
|
955
|
+
},
|
|
956
|
+
args: {
|
|
957
|
+
path: {
|
|
958
|
+
type: 'positional',
|
|
959
|
+
description: 'Path to repository directory (default: cwd)',
|
|
960
|
+
required: false,
|
|
961
|
+
},
|
|
962
|
+
json: {
|
|
963
|
+
type: 'boolean',
|
|
964
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
965
|
+
},
|
|
966
|
+
'project-id': {
|
|
967
|
+
type: 'string',
|
|
968
|
+
description: 'Override the project ID (default: auto-detected)',
|
|
969
|
+
},
|
|
970
|
+
incremental: {
|
|
971
|
+
type: 'boolean',
|
|
972
|
+
description: 'Only re-index files that have changed since the last run (faster)',
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
async run({ args }) {
|
|
976
|
+
const startTime = Date.now();
|
|
977
|
+
const jsonOutput = !!args.json;
|
|
978
|
+
const projectIdOverride = args['project-id'];
|
|
979
|
+
const isIncremental = !!args.incremental;
|
|
980
|
+
// Resolve target path
|
|
981
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
982
|
+
if (!jsonOutput) {
|
|
983
|
+
process.stderr.write(`[nexus] Analyzing: ${repoPath}${isIncremental ? ' (incremental)' : ''}\n`);
|
|
984
|
+
}
|
|
985
|
+
try {
|
|
986
|
+
// SSoT-EXEMPT:pipeline-progress — runPipeline requires a progress callback
|
|
987
|
+
// (CLI-only rendering concern) and direct DB handle access. No dispatch op
|
|
988
|
+
// can expose this without introducing CLI rendering concerns into the dispatch
|
|
989
|
+
// layer. The full analyze pipeline is fundamentally CLI-side-orchestrated.
|
|
990
|
+
// Lazy imports to avoid loading heavy dependencies until needed
|
|
991
|
+
const [{ getNexusDb, nexusSchema }, { runPipeline }, { getProjectRoot }, { eq }] = await Promise.all([
|
|
992
|
+
import('@cleocode/core/store/nexus-sqlite'),
|
|
993
|
+
import('@cleocode/nexus/pipeline'),
|
|
994
|
+
import('@cleocode/core/internal'),
|
|
995
|
+
import('drizzle-orm'),
|
|
996
|
+
]);
|
|
997
|
+
// Determine project ID — use override or derive from path
|
|
998
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
999
|
+
// Get DB and table references
|
|
1000
|
+
const db = await getNexusDb();
|
|
1001
|
+
const tables = {
|
|
1002
|
+
nexusNodes: nexusSchema.nexusNodes,
|
|
1003
|
+
nexusRelations: nexusSchema.nexusRelations,
|
|
1004
|
+
};
|
|
1005
|
+
// For full (non-incremental) runs: delete existing index first.
|
|
1006
|
+
// NodeSQLiteDatabase uses sync Drizzle — no await, wrap in try-catch.
|
|
1007
|
+
if (!isIncremental) {
|
|
1008
|
+
if (!jsonOutput) {
|
|
1009
|
+
process.stderr.write('[nexus] Clearing existing index for project...\n');
|
|
1010
|
+
}
|
|
1011
|
+
try {
|
|
1012
|
+
db.delete(nexusSchema.nexusNodes)
|
|
1013
|
+
.where(eq(nexusSchema.nexusNodes.projectId, projectId))
|
|
1014
|
+
.run();
|
|
1015
|
+
}
|
|
1016
|
+
catch {
|
|
1017
|
+
// Table may not have rows — ignore
|
|
1018
|
+
}
|
|
1019
|
+
try {
|
|
1020
|
+
db.delete(nexusSchema.nexusRelations)
|
|
1021
|
+
.where(eq(nexusSchema.nexusRelations.projectId, projectId))
|
|
1022
|
+
.run();
|
|
1023
|
+
}
|
|
1024
|
+
catch {
|
|
1025
|
+
// Table may not have rows — ignore
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
// Run the pipeline (full or incremental)
|
|
1029
|
+
const result = await runPipeline(repoPath, projectId, db, tables, jsonOutput
|
|
1030
|
+
? undefined
|
|
1031
|
+
: (current, total, filePath) => {
|
|
1032
|
+
if (current % 50 === 0 || current === total) {
|
|
1033
|
+
const pct = total > 0 ? Math.round((current / total) * 100) : 100;
|
|
1034
|
+
process.stderr.write(`[nexus] Progress: ${current}/${total} files (${pct}%) — ${filePath}\n`);
|
|
1035
|
+
}
|
|
1036
|
+
}, { incremental: isIncremental });
|
|
1037
|
+
const durationMs = Date.now() - startTime;
|
|
1038
|
+
// Write nexus-bridge.md after a successful pipeline run (best-effort)
|
|
1039
|
+
try {
|
|
1040
|
+
const { refreshNexusBridge } = await import('@cleocode/core/internal');
|
|
1041
|
+
await refreshNexusBridge(repoPath, projectId);
|
|
1042
|
+
if (!jsonOutput) {
|
|
1043
|
+
process.stderr.write(`[nexus] nexus-bridge.md refreshed at ${repoPath}/.cleo/nexus-bridge.md\n`);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
catch {
|
|
1047
|
+
// Non-fatal — bridge refresh failure should not fail the analyze command
|
|
1048
|
+
}
|
|
1049
|
+
// Auto-register project and update index stats in the multi-project registry (best-effort)
|
|
1050
|
+
try {
|
|
1051
|
+
const { nexusUpdateIndexStats } = await import('@cleocode/core/internal');
|
|
1052
|
+
await nexusUpdateIndexStats(repoPath, {
|
|
1053
|
+
nodeCount: result.nodeCount,
|
|
1054
|
+
relationCount: result.relationCount,
|
|
1055
|
+
fileCount: result.fileCount,
|
|
1056
|
+
});
|
|
1057
|
+
if (!jsonOutput) {
|
|
1058
|
+
process.stderr.write('[nexus] Project registered/updated in multi-project registry.\n');
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
catch {
|
|
1062
|
+
// Non-fatal — registry update must never fail the analyze command
|
|
1063
|
+
}
|
|
1064
|
+
// Post-hook: sweep git log and link task IDs to symbols (best-effort, idempotent)
|
|
1065
|
+
try {
|
|
1066
|
+
const { runGitLogTaskLinker } = await import('@cleocode/core/nexus');
|
|
1067
|
+
const sweeperResult = await runGitLogTaskLinker(repoPath);
|
|
1068
|
+
if (!jsonOutput && sweeperResult.commitsProcessed > 0) {
|
|
1069
|
+
process.stderr.write(`[nexus] Task-symbol sweep: ${sweeperResult.commitsProcessed} commit(s), ${sweeperResult.tasksFound} task(s), ${sweeperResult.linked} edge(s) linked.\n`);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
catch {
|
|
1073
|
+
// Non-fatal — task sweeper failure must never fail the analyze command
|
|
1074
|
+
}
|
|
1075
|
+
if (jsonOutput) {
|
|
1076
|
+
const envelope = {
|
|
1077
|
+
success: true,
|
|
1078
|
+
data: {
|
|
1079
|
+
projectId,
|
|
1080
|
+
repoPath,
|
|
1081
|
+
incremental: isIncremental,
|
|
1082
|
+
nodeCount: result.nodeCount,
|
|
1083
|
+
relationCount: result.relationCount,
|
|
1084
|
+
fileCount: result.fileCount,
|
|
1085
|
+
durationMs,
|
|
1086
|
+
},
|
|
1087
|
+
meta: {
|
|
1088
|
+
operation: 'nexus.analyze',
|
|
1089
|
+
duration_ms: durationMs,
|
|
1090
|
+
timestamp: new Date().toISOString(),
|
|
1091
|
+
},
|
|
1092
|
+
};
|
|
1093
|
+
process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
|
|
1094
|
+
}
|
|
1095
|
+
else {
|
|
1096
|
+
process.stdout.write(`[nexus] Analysis complete${isIncremental ? ' (incremental)' : ''}:\n` +
|
|
1097
|
+
` Project ID: ${projectId}\n` +
|
|
1098
|
+
` Files: ${result.fileCount}\n` +
|
|
1099
|
+
` Nodes: ${result.nodeCount}\n` +
|
|
1100
|
+
` Relations: ${result.relationCount}\n` +
|
|
1101
|
+
` Duration: ${durationMs}ms\n`);
|
|
1102
|
+
}
|
|
1103
|
+
void getProjectRoot; // referenced to satisfy import
|
|
1104
|
+
}
|
|
1105
|
+
catch (err) {
|
|
1106
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1107
|
+
if (jsonOutput) {
|
|
1108
|
+
const envelope = {
|
|
1109
|
+
success: false,
|
|
1110
|
+
error: { code: 'E_PIPELINE_FAILED', message: msg },
|
|
1111
|
+
meta: {
|
|
1112
|
+
operation: 'nexus.analyze',
|
|
1113
|
+
duration_ms: Date.now() - startTime,
|
|
1114
|
+
timestamp: new Date().toISOString(),
|
|
1115
|
+
},
|
|
1116
|
+
};
|
|
1117
|
+
process.stdout.write(JSON.stringify(envelope, null, 2) + '\n');
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1121
|
+
}
|
|
1122
|
+
process.exitCode = 1;
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
});
|
|
1126
|
+
// ── nexus projects subcommand group ──────────────────────────────────────────
|
|
1127
|
+
/** cleo nexus projects list — list all projects registered in the global nexus registry */
|
|
1128
|
+
const projectsListCommand = defineCommand({
|
|
1129
|
+
meta: {
|
|
1130
|
+
name: 'list',
|
|
1131
|
+
description: 'List all projects registered in the global nexus registry',
|
|
1132
|
+
},
|
|
1133
|
+
args: {
|
|
1134
|
+
json: {
|
|
1135
|
+
type: 'boolean',
|
|
1136
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
1137
|
+
},
|
|
1138
|
+
},
|
|
1139
|
+
async run({ args }) {
|
|
1140
|
+
const startTime = Date.now();
|
|
1141
|
+
const jsonOutput = !!args.json;
|
|
1142
|
+
const response = await dispatchRaw('query', 'nexus', 'projects.list', {});
|
|
1143
|
+
const durationMs = Date.now() - startTime;
|
|
1144
|
+
if (!response.success) {
|
|
1145
|
+
process.stderr.write(`[nexus] Error: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
1146
|
+
process.exitCode = 1;
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
const data = response.data;
|
|
1150
|
+
const list = data.projects;
|
|
1151
|
+
if (jsonOutput) {
|
|
1152
|
+
process.stdout.write(JSON.stringify({
|
|
1153
|
+
success: true,
|
|
1154
|
+
data,
|
|
1155
|
+
meta: {
|
|
1156
|
+
operation: 'nexus.projects.list',
|
|
1157
|
+
duration_ms: durationMs,
|
|
1158
|
+
timestamp: new Date().toISOString(),
|
|
1159
|
+
},
|
|
1160
|
+
}, null, 2) + '\n');
|
|
1161
|
+
}
|
|
1162
|
+
else if (list.length === 0) {
|
|
1163
|
+
process.stdout.write('[nexus] No projects registered. Run: cleo nexus projects register\n');
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
process.stdout.write(`[nexus] Registered projects (${list.length}):\n\n`);
|
|
1167
|
+
for (const p of list) {
|
|
1168
|
+
const nodes = p.stats?.nodeCount ?? 0;
|
|
1169
|
+
const rels = p.stats?.relationCount ?? 0;
|
|
1170
|
+
const indexed = p.lastIndexed ? p.lastIndexed.slice(0, 10) : 'never';
|
|
1171
|
+
process.stdout.write(` ${p.name.padEnd(28)} tasks=${String(p.taskCount).padStart(5)} nodes=${String(nodes).padStart(6)} relations=${String(rels).padStart(7)} indexed=${indexed}\n` +
|
|
1172
|
+
` ${''.padEnd(28)} path=${p.path}\n`);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
},
|
|
1176
|
+
});
|
|
1177
|
+
/** cleo nexus projects register — register a project in the global nexus registry */
|
|
1178
|
+
const projectsRegisterCommand = defineCommand({
|
|
1179
|
+
meta: {
|
|
1180
|
+
name: 'register',
|
|
1181
|
+
description: 'Register a project in the global nexus registry (default: current directory)',
|
|
1182
|
+
},
|
|
1183
|
+
args: {
|
|
1184
|
+
path: {
|
|
1185
|
+
type: 'positional',
|
|
1186
|
+
description: 'Path to the project directory (default: cwd)',
|
|
1187
|
+
required: false,
|
|
1188
|
+
},
|
|
1189
|
+
name: {
|
|
1190
|
+
type: 'string',
|
|
1191
|
+
description: 'Custom project name (default: directory name)',
|
|
1192
|
+
},
|
|
1193
|
+
json: {
|
|
1194
|
+
type: 'boolean',
|
|
1195
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
1196
|
+
},
|
|
1197
|
+
},
|
|
1198
|
+
async run({ args }) {
|
|
1199
|
+
const startTime = Date.now();
|
|
1200
|
+
const jsonOutput = !!args.json;
|
|
1201
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
1202
|
+
const name = args.name;
|
|
1203
|
+
const response = await dispatchRaw('mutate', 'nexus', 'projects.register', {
|
|
1204
|
+
path: repoPath,
|
|
1205
|
+
name,
|
|
1206
|
+
});
|
|
1207
|
+
const durationMs = Date.now() - startTime;
|
|
1208
|
+
if (!response.success) {
|
|
1209
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1210
|
+
if (jsonOutput) {
|
|
1211
|
+
process.stdout.write(JSON.stringify({
|
|
1212
|
+
success: false,
|
|
1213
|
+
error: { code: response.error?.code ?? 'E_REGISTER_FAILED', message: msg },
|
|
1214
|
+
meta: {
|
|
1215
|
+
operation: 'nexus.projects.register',
|
|
1216
|
+
duration_ms: durationMs,
|
|
1217
|
+
timestamp: new Date().toISOString(),
|
|
1218
|
+
},
|
|
1219
|
+
}, null, 2) + '\n');
|
|
1220
|
+
}
|
|
1221
|
+
else {
|
|
1222
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1223
|
+
}
|
|
1224
|
+
process.exitCode = 1;
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
const data = response.data;
|
|
1228
|
+
if (jsonOutput) {
|
|
1229
|
+
process.stdout.write(JSON.stringify({
|
|
1230
|
+
success: true,
|
|
1231
|
+
data,
|
|
1232
|
+
meta: {
|
|
1233
|
+
operation: 'nexus.projects.register',
|
|
1234
|
+
duration_ms: durationMs,
|
|
1235
|
+
timestamp: new Date().toISOString(),
|
|
1236
|
+
},
|
|
1237
|
+
}, null, 2) + '\n');
|
|
1238
|
+
}
|
|
1239
|
+
else {
|
|
1240
|
+
process.stdout.write(`[nexus] Registered: ${data.path} (hash: ${data.hash})\n`);
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
});
|
|
1244
|
+
/** cleo nexus projects remove — remove a project from the global nexus registry */
|
|
1245
|
+
const projectsRemoveCommand = defineCommand({
|
|
1246
|
+
meta: {
|
|
1247
|
+
name: 'remove',
|
|
1248
|
+
description: 'Remove a project from the global nexus registry',
|
|
1249
|
+
},
|
|
1250
|
+
args: {
|
|
1251
|
+
nameOrHash: {
|
|
1252
|
+
type: 'positional',
|
|
1253
|
+
description: 'Project name or hash to remove',
|
|
1254
|
+
required: true,
|
|
1255
|
+
},
|
|
1256
|
+
json: {
|
|
1257
|
+
type: 'boolean',
|
|
1258
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
1259
|
+
},
|
|
1260
|
+
},
|
|
1261
|
+
async run({ args }) {
|
|
1262
|
+
const startTime = Date.now();
|
|
1263
|
+
const jsonOutput = !!args.json;
|
|
1264
|
+
const response = await dispatchRaw('mutate', 'nexus', 'projects.remove', {
|
|
1265
|
+
nameOrHash: args.nameOrHash,
|
|
1266
|
+
});
|
|
1267
|
+
const durationMs = Date.now() - startTime;
|
|
1268
|
+
if (!response.success) {
|
|
1269
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1270
|
+
if (jsonOutput) {
|
|
1271
|
+
process.stdout.write(JSON.stringify({
|
|
1272
|
+
success: false,
|
|
1273
|
+
error: { code: response.error?.code ?? 'E_REMOVE_FAILED', message: msg },
|
|
1274
|
+
meta: {
|
|
1275
|
+
operation: 'nexus.projects.remove',
|
|
1276
|
+
duration_ms: durationMs,
|
|
1277
|
+
timestamp: new Date().toISOString(),
|
|
1278
|
+
},
|
|
1279
|
+
}, null, 2) + '\n');
|
|
1280
|
+
}
|
|
1281
|
+
else {
|
|
1282
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1283
|
+
}
|
|
1284
|
+
process.exitCode = 1;
|
|
1285
|
+
return;
|
|
1286
|
+
}
|
|
1287
|
+
if (jsonOutput) {
|
|
1288
|
+
process.stdout.write(JSON.stringify({
|
|
1289
|
+
success: true,
|
|
1290
|
+
data: response.data,
|
|
1291
|
+
meta: {
|
|
1292
|
+
operation: 'nexus.projects.remove',
|
|
1293
|
+
duration_ms: durationMs,
|
|
1294
|
+
timestamp: new Date().toISOString(),
|
|
1295
|
+
},
|
|
1296
|
+
}, null, 2) + '\n');
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
process.stdout.write(`[nexus] Removed: ${String(args.nameOrHash)}\n`);
|
|
1300
|
+
}
|
|
1301
|
+
},
|
|
1302
|
+
});
|
|
1303
|
+
/** cleo nexus projects scan — walk filesystem roots to discover .cleo/ directories */
|
|
1304
|
+
const projectsScanCommand = defineCommand({
|
|
1305
|
+
meta: {
|
|
1306
|
+
name: 'scan',
|
|
1307
|
+
description: 'Walk filesystem roots to discover .cleo/ directories not registered in the global nexus registry',
|
|
1308
|
+
},
|
|
1309
|
+
args: {
|
|
1310
|
+
roots: {
|
|
1311
|
+
type: 'string',
|
|
1312
|
+
description: 'Comma-separated search roots (default: ~/code,~/projects,/mnt/projects)',
|
|
1313
|
+
},
|
|
1314
|
+
'max-depth': {
|
|
1315
|
+
type: 'string',
|
|
1316
|
+
description: 'Maximum directory traversal depth (default: 4)',
|
|
1317
|
+
default: '4',
|
|
1318
|
+
},
|
|
1319
|
+
'auto-register': {
|
|
1320
|
+
type: 'boolean',
|
|
1321
|
+
description: 'Register all discovered unregistered projects automatically',
|
|
1322
|
+
},
|
|
1323
|
+
'include-existing': {
|
|
1324
|
+
type: 'boolean',
|
|
1325
|
+
description: 'Also report projects that are already registered',
|
|
1326
|
+
},
|
|
1327
|
+
json: { type: 'boolean', description: 'Output as JSON (LAFS envelope format)' },
|
|
1328
|
+
},
|
|
1329
|
+
async run({ args }) {
|
|
1330
|
+
const startTime = Date.now();
|
|
1331
|
+
const jsonOutput = !!args.json;
|
|
1332
|
+
const autoRegister = !!args['auto-register'];
|
|
1333
|
+
const includeExisting = !!args['include-existing'];
|
|
1334
|
+
const maxDepth = Math.max(1, Math.min(parseInt(args['max-depth'], 10), 20));
|
|
1335
|
+
if (!jsonOutput) {
|
|
1336
|
+
process.stdout.write(`[nexus] Scanning up to depth ${maxDepth} for .cleo/ project roots...\n`);
|
|
1337
|
+
}
|
|
1338
|
+
const response = await dispatchRaw('mutate', 'nexus', 'projects.scan', {
|
|
1339
|
+
roots: args.roots,
|
|
1340
|
+
maxDepth,
|
|
1341
|
+
autoRegister,
|
|
1342
|
+
includeExisting,
|
|
1343
|
+
});
|
|
1344
|
+
const durationMs = Date.now() - startTime;
|
|
1345
|
+
if (!response.success) {
|
|
1346
|
+
process.stderr.write(`[nexus] Error: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
1347
|
+
process.exitCode = 1;
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const result = response.data;
|
|
1351
|
+
if (!jsonOutput) {
|
|
1352
|
+
process.stdout.write(`[nexus] Scanning ${result.roots.length} root(s) up to depth ${maxDepth}:\n${result.roots.map((r) => ` ${r}`).join('\n')}\n`);
|
|
1353
|
+
}
|
|
1354
|
+
if (jsonOutput) {
|
|
1355
|
+
const data = {
|
|
1356
|
+
roots: result.roots,
|
|
1357
|
+
unregistered: result.unregistered,
|
|
1358
|
+
tally: result.tally,
|
|
1359
|
+
};
|
|
1360
|
+
if (includeExisting)
|
|
1361
|
+
data['registered'] = result.registered;
|
|
1362
|
+
if (autoRegister) {
|
|
1363
|
+
data['autoRegistered'] = result.autoRegistered;
|
|
1364
|
+
data['autoRegisterErrors'] = result.autoRegisterErrors;
|
|
1365
|
+
}
|
|
1366
|
+
process.stdout.write(JSON.stringify({
|
|
1367
|
+
success: true,
|
|
1368
|
+
data,
|
|
1369
|
+
meta: {
|
|
1370
|
+
operation: 'nexus.projects.scan',
|
|
1371
|
+
duration_ms: durationMs,
|
|
1372
|
+
timestamp: new Date().toISOString(),
|
|
1373
|
+
},
|
|
1374
|
+
}, null, 2) + '\n');
|
|
1375
|
+
}
|
|
1376
|
+
else {
|
|
1377
|
+
process.stdout.write(`\n[nexus] Scan complete — ${result.tally.total} project(s) found (${result.tally.unregistered} unregistered, ${result.tally.registered} registered)\n`);
|
|
1378
|
+
if (result.unregistered.length > 0) {
|
|
1379
|
+
process.stdout.write('\n Unregistered:\n');
|
|
1380
|
+
for (const p of result.unregistered) {
|
|
1381
|
+
process.stdout.write(` ${p}\n`);
|
|
1382
|
+
}
|
|
1383
|
+
if (!autoRegister) {
|
|
1384
|
+
process.stdout.write('\n Tip: run with --auto-register to register all of the above.\n');
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
if (includeExisting && result.registered.length > 0) {
|
|
1388
|
+
process.stdout.write('\n Already registered:\n');
|
|
1389
|
+
for (const p of result.registered) {
|
|
1390
|
+
process.stdout.write(` ${p}\n`);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
if (autoRegister) {
|
|
1394
|
+
process.stdout.write(`\n Auto-registered: ${result.autoRegistered.length} project(s)${result.autoRegisterErrors.length > 0 ? `, ${result.autoRegisterErrors.length} failed` : ''}\n`);
|
|
1395
|
+
for (const e of result.autoRegisterErrors) {
|
|
1396
|
+
process.stdout.write(` FAILED ${e.path}: ${e.error}\n`);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
},
|
|
1401
|
+
});
|
|
1402
|
+
/** cleo nexus projects clean — bulk purge project_registry rows matching path criteria */
|
|
1403
|
+
const projectsCleanCommand = defineCommand({
|
|
1404
|
+
meta: {
|
|
1405
|
+
name: 'clean',
|
|
1406
|
+
description: 'Bulk purge project_registry rows matching path criteria (requires at least one filter flag)',
|
|
1407
|
+
},
|
|
1408
|
+
args: {
|
|
1409
|
+
'dry-run': {
|
|
1410
|
+
type: 'boolean',
|
|
1411
|
+
description: 'List matching projects without deleting anything',
|
|
1412
|
+
},
|
|
1413
|
+
pattern: {
|
|
1414
|
+
type: 'string',
|
|
1415
|
+
description: 'JS regex matched against project_path',
|
|
1416
|
+
},
|
|
1417
|
+
'include-temp': {
|
|
1418
|
+
type: 'boolean',
|
|
1419
|
+
description: 'Preset: match paths containing a .temp/ segment',
|
|
1420
|
+
},
|
|
1421
|
+
'include-tests': {
|
|
1422
|
+
type: 'boolean',
|
|
1423
|
+
description: 'Preset: match paths containing tmp/test/fixture/scratch/sandbox segments',
|
|
1424
|
+
},
|
|
1425
|
+
unhealthy: {
|
|
1426
|
+
type: 'boolean',
|
|
1427
|
+
description: 'Also match rows where health_status is "unhealthy"',
|
|
1428
|
+
},
|
|
1429
|
+
'never-indexed': {
|
|
1430
|
+
type: 'boolean',
|
|
1431
|
+
description: 'Also match rows where last_indexed IS NULL',
|
|
1432
|
+
},
|
|
1433
|
+
yes: {
|
|
1434
|
+
type: 'boolean',
|
|
1435
|
+
description: 'Skip confirmation prompt (still shows preview)',
|
|
1436
|
+
},
|
|
1437
|
+
json: {
|
|
1438
|
+
type: 'boolean',
|
|
1439
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
1440
|
+
},
|
|
1441
|
+
},
|
|
1442
|
+
async run({ args }) {
|
|
1443
|
+
const startTime = Date.now();
|
|
1444
|
+
const jsonOutput = !!args.json;
|
|
1445
|
+
const dryRun = !!args['dry-run'];
|
|
1446
|
+
const skipPrompt = !!args.yes;
|
|
1447
|
+
const cleanOpts = {
|
|
1448
|
+
pattern: args.pattern,
|
|
1449
|
+
includeTemp: !!args['include-temp'],
|
|
1450
|
+
includeTests: !!args['include-tests'],
|
|
1451
|
+
matchUnhealthy: !!args.unhealthy,
|
|
1452
|
+
matchNeverIndexed: !!args['never-indexed'],
|
|
1453
|
+
};
|
|
1454
|
+
try {
|
|
1455
|
+
// Preview phase via dispatch (always dry-run first to get counts)
|
|
1456
|
+
const previewResp = await dispatchRaw('mutate', 'nexus', 'projects.clean', {
|
|
1457
|
+
...cleanOpts,
|
|
1458
|
+
dryRun: true,
|
|
1459
|
+
});
|
|
1460
|
+
if (!previewResp.success) {
|
|
1461
|
+
const code = previewResp.error?.code ?? 'E_CLEAN_FAILED';
|
|
1462
|
+
const msg = previewResp.error?.message ?? 'Unknown error';
|
|
1463
|
+
const exitCode = code === 'E_NO_CRITERIA' || code === 'E_INVALID_PATTERN' ? 6 : 1;
|
|
1464
|
+
if (jsonOutput) {
|
|
1465
|
+
process.stdout.write(JSON.stringify({
|
|
1466
|
+
success: false,
|
|
1467
|
+
error: { code, message: msg },
|
|
1468
|
+
meta: {
|
|
1469
|
+
operation: 'nexus.projects.clean',
|
|
1470
|
+
duration_ms: Date.now() - startTime,
|
|
1471
|
+
timestamp: new Date().toISOString(),
|
|
1472
|
+
},
|
|
1473
|
+
}, null, 2) + '\n');
|
|
1474
|
+
}
|
|
1475
|
+
else {
|
|
1476
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1477
|
+
}
|
|
1478
|
+
process.exitCode = exitCode;
|
|
1479
|
+
return;
|
|
1480
|
+
}
|
|
1481
|
+
const preview = previewResp.data;
|
|
1482
|
+
const { matched: matchCount, totalCount, sample: samplePaths } = preview;
|
|
1483
|
+
// Show preview in human mode
|
|
1484
|
+
if (!jsonOutput) {
|
|
1485
|
+
process.stdout.write(`[nexus] Clean preview — ${matchCount} project(s) of ${totalCount} total match criteria:\n`);
|
|
1486
|
+
if (matchCount === 0) {
|
|
1487
|
+
process.stdout.write(' (no matches)\n');
|
|
1488
|
+
}
|
|
1489
|
+
else {
|
|
1490
|
+
for (const p of samplePaths) {
|
|
1491
|
+
process.stdout.write(` ${p}\n`);
|
|
1492
|
+
}
|
|
1493
|
+
if (matchCount > 10) {
|
|
1494
|
+
process.stdout.write(` ... and ${matchCount - 10} more\n`);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
if (matchCount === 0 || dryRun) {
|
|
1499
|
+
const durationMs = Date.now() - startTime;
|
|
1500
|
+
if (jsonOutput) {
|
|
1501
|
+
process.stdout.write(JSON.stringify({
|
|
1502
|
+
success: true,
|
|
1503
|
+
data: {
|
|
1504
|
+
dryRun: true,
|
|
1505
|
+
matched: matchCount,
|
|
1506
|
+
purged: 0,
|
|
1507
|
+
remaining: totalCount,
|
|
1508
|
+
sample: samplePaths,
|
|
1509
|
+
},
|
|
1510
|
+
meta: {
|
|
1511
|
+
operation: 'nexus.projects.clean',
|
|
1512
|
+
duration_ms: durationMs,
|
|
1513
|
+
timestamp: new Date().toISOString(),
|
|
1514
|
+
},
|
|
1515
|
+
}, null, 2) + '\n');
|
|
1516
|
+
}
|
|
1517
|
+
else if (dryRun && matchCount > 0) {
|
|
1518
|
+
process.stdout.write(`[nexus] Dry-run — ${matchCount} project(s) would be purged. Rerun without --dry-run to delete.\n`);
|
|
1519
|
+
}
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
// Confirmation prompt (skip with --yes) — CLI-side interactive stdin
|
|
1523
|
+
if (!skipPrompt) {
|
|
1524
|
+
const { createInterface } = await import('node:readline');
|
|
1525
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
1526
|
+
const confirmed = await new Promise((resolve) => {
|
|
1527
|
+
rl.question(`\n[nexus] Delete ${matchCount} project(s) from the registry? [y/N] `, (answer) => {
|
|
1528
|
+
rl.close();
|
|
1529
|
+
resolve(answer.trim().toLowerCase() === 'y');
|
|
1530
|
+
});
|
|
1531
|
+
});
|
|
1532
|
+
if (!confirmed) {
|
|
1533
|
+
process.stdout.write('[nexus] Aborted — no projects deleted.\n');
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
// Actual delete via dispatch
|
|
1538
|
+
const deleteResp = await dispatchRaw('mutate', 'nexus', 'projects.clean', {
|
|
1539
|
+
...cleanOpts,
|
|
1540
|
+
dryRun: false,
|
|
1541
|
+
});
|
|
1542
|
+
const durationMs = Date.now() - startTime;
|
|
1543
|
+
if (!deleteResp.success) {
|
|
1544
|
+
const code = deleteResp.error?.code ?? 'E_CLEAN_FAILED';
|
|
1545
|
+
const msg = deleteResp.error?.message ?? 'Unknown error';
|
|
1546
|
+
const exitCode = code === 'E_NO_CRITERIA' || code === 'E_INVALID_PATTERN' ? 6 : 1;
|
|
1547
|
+
if (jsonOutput) {
|
|
1548
|
+
process.stdout.write(JSON.stringify({
|
|
1549
|
+
success: false,
|
|
1550
|
+
error: { code, message: msg },
|
|
1551
|
+
meta: {
|
|
1552
|
+
operation: 'nexus.projects.clean',
|
|
1553
|
+
duration_ms: durationMs,
|
|
1554
|
+
timestamp: new Date().toISOString(),
|
|
1555
|
+
},
|
|
1556
|
+
}, null, 2) + '\n');
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1560
|
+
}
|
|
1561
|
+
process.exitCode = exitCode;
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
const result = deleteResp.data;
|
|
1565
|
+
if (jsonOutput) {
|
|
1566
|
+
process.stdout.write(JSON.stringify({
|
|
1567
|
+
success: true,
|
|
1568
|
+
data: {
|
|
1569
|
+
dryRun: false,
|
|
1570
|
+
matched: result.matched,
|
|
1571
|
+
purged: result.purged,
|
|
1572
|
+
remaining: result.remaining,
|
|
1573
|
+
sample: result.sample,
|
|
1574
|
+
},
|
|
1575
|
+
meta: {
|
|
1576
|
+
operation: 'nexus.projects.clean',
|
|
1577
|
+
duration_ms: durationMs,
|
|
1578
|
+
timestamp: new Date().toISOString(),
|
|
1579
|
+
},
|
|
1580
|
+
}, null, 2) + '\n');
|
|
1581
|
+
}
|
|
1582
|
+
else {
|
|
1583
|
+
process.stdout.write(`[nexus] Purged ${result.purged} project(s). ${result.remaining} project(s) remaining in registry.\n`);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
catch (err) {
|
|
1587
|
+
const durationMs = Date.now() - startTime;
|
|
1588
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1589
|
+
if (jsonOutput) {
|
|
1590
|
+
process.stdout.write(JSON.stringify({
|
|
1591
|
+
success: false,
|
|
1592
|
+
error: { code: 'E_CLEAN_FAILED', message: msg },
|
|
1593
|
+
meta: {
|
|
1594
|
+
operation: 'nexus.projects.clean',
|
|
1595
|
+
duration_ms: durationMs,
|
|
1596
|
+
timestamp: new Date().toISOString(),
|
|
1597
|
+
},
|
|
1598
|
+
}, null, 2) + '\n');
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1602
|
+
}
|
|
1603
|
+
process.exitCode = 1;
|
|
1604
|
+
}
|
|
1605
|
+
},
|
|
1606
|
+
});
|
|
1607
|
+
/** cleo nexus projects — multi-project registry management */
|
|
1608
|
+
const projectsCommand = defineCommand({
|
|
1609
|
+
meta: { name: 'projects', description: 'Multi-project registry management' },
|
|
1610
|
+
subCommands: {
|
|
1611
|
+
list: projectsListCommand,
|
|
1612
|
+
register: projectsRegisterCommand,
|
|
1613
|
+
remove: projectsRemoveCommand,
|
|
1614
|
+
scan: projectsScanCommand,
|
|
1615
|
+
clean: projectsCleanCommand,
|
|
1616
|
+
},
|
|
1617
|
+
});
|
|
1618
|
+
/** cleo nexus refresh-bridge — regenerate .cleo/nexus-bridge.md from existing index */
|
|
1619
|
+
const refreshBridgeCommand = defineCommand({
|
|
1620
|
+
meta: {
|
|
1621
|
+
name: 'refresh-bridge',
|
|
1622
|
+
description: 'Regenerate .cleo/nexus-bridge.md from the existing nexus.db index (does not re-index)',
|
|
1623
|
+
},
|
|
1624
|
+
args: {
|
|
1625
|
+
path: {
|
|
1626
|
+
type: 'positional',
|
|
1627
|
+
description: 'Path to project directory (default: cwd)',
|
|
1628
|
+
required: false,
|
|
1629
|
+
},
|
|
1630
|
+
json: {
|
|
1631
|
+
type: 'boolean',
|
|
1632
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
1633
|
+
},
|
|
1634
|
+
'project-id': {
|
|
1635
|
+
type: 'string',
|
|
1636
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
1637
|
+
},
|
|
1638
|
+
},
|
|
1639
|
+
async run({ args }) {
|
|
1640
|
+
const startTime = Date.now();
|
|
1641
|
+
const jsonOutput = !!args.json;
|
|
1642
|
+
const projectIdOverride = args['project-id'];
|
|
1643
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
1644
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
1645
|
+
const response = await dispatchRaw('mutate', 'nexus', 'refresh-bridge', {
|
|
1646
|
+
repoPath,
|
|
1647
|
+
projectId,
|
|
1648
|
+
});
|
|
1649
|
+
const durationMs = Date.now() - startTime;
|
|
1650
|
+
if (!response.success) {
|
|
1651
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1652
|
+
if (jsonOutput) {
|
|
1653
|
+
process.stdout.write(JSON.stringify({
|
|
1654
|
+
success: false,
|
|
1655
|
+
error: { code: response.error?.code ?? 'E_BRIDGE_FAILED', message: msg },
|
|
1656
|
+
meta: {
|
|
1657
|
+
operation: 'nexus.refresh-bridge',
|
|
1658
|
+
duration_ms: durationMs,
|
|
1659
|
+
timestamp: new Date().toISOString(),
|
|
1660
|
+
},
|
|
1661
|
+
}, null, 2) + '\n');
|
|
1662
|
+
}
|
|
1663
|
+
else {
|
|
1664
|
+
process.stderr.write(`[nexus] Error refreshing bridge: ${msg}\n`);
|
|
1665
|
+
}
|
|
1666
|
+
process.exitCode = 1;
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
const result = response.data;
|
|
1670
|
+
if (jsonOutput) {
|
|
1671
|
+
process.stdout.write(JSON.stringify({
|
|
1672
|
+
success: true,
|
|
1673
|
+
data: result,
|
|
1674
|
+
meta: {
|
|
1675
|
+
operation: 'nexus.refresh-bridge',
|
|
1676
|
+
duration_ms: durationMs,
|
|
1677
|
+
timestamp: new Date().toISOString(),
|
|
1678
|
+
},
|
|
1679
|
+
}, null, 2) + '\n');
|
|
1680
|
+
}
|
|
1681
|
+
else if (result.written) {
|
|
1682
|
+
process.stdout.write(`[nexus] nexus-bridge.md refreshed at ${result.path}\n`);
|
|
1683
|
+
}
|
|
1684
|
+
else {
|
|
1685
|
+
process.stdout.write(`[nexus] nexus-bridge.md unchanged at ${result.path}\n`);
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
});
|
|
1689
|
+
/**
|
|
1690
|
+
* Export nexus graph to GEXF (Gephi) or JSON format.
|
|
1691
|
+
*
|
|
1692
|
+
* Queries graph_nodes and graph_edges from nexus.db and emits GEXF format
|
|
1693
|
+
* suitable for visualization in Gephi. Supports optional project filtering.
|
|
1694
|
+
*
|
|
1695
|
+
* @task T626-M7
|
|
1696
|
+
*/
|
|
1697
|
+
const exportCommand = defineCommand({
|
|
1698
|
+
meta: { name: 'export', description: 'Export nexus graph to GEXF (Gephi) or JSON format' },
|
|
1699
|
+
args: {
|
|
1700
|
+
format: {
|
|
1701
|
+
type: 'string',
|
|
1702
|
+
description: 'Output format: gexf, json',
|
|
1703
|
+
default: 'gexf',
|
|
1704
|
+
},
|
|
1705
|
+
output: {
|
|
1706
|
+
type: 'string',
|
|
1707
|
+
description: 'Output file path (stdout if omitted)',
|
|
1708
|
+
},
|
|
1709
|
+
project: {
|
|
1710
|
+
type: 'string',
|
|
1711
|
+
description: 'Filter by project ID (exports all projects if omitted)',
|
|
1712
|
+
},
|
|
1713
|
+
},
|
|
1714
|
+
async run({ args }) {
|
|
1715
|
+
const startTime = Date.now();
|
|
1716
|
+
const format = args.format ?? 'gexf';
|
|
1717
|
+
const outputFile = args.output;
|
|
1718
|
+
const projectFilter = args.project;
|
|
1719
|
+
try {
|
|
1720
|
+
// SSoT-EXEMPT:file-serialization — GEXF/JSON graph export writes raw bytes
|
|
1721
|
+
// to stdout/file; requires direct nexus.db access for node/relation queries.
|
|
1722
|
+
// Cannot be a standard LAFS dispatch envelope without binary data concerns.
|
|
1723
|
+
const { getNexusDb, nexusSchema } = await import('@cleocode/core/store/nexus-sqlite');
|
|
1724
|
+
const db = await getNexusDb();
|
|
1725
|
+
// Load all nodes and relations
|
|
1726
|
+
let allNodes = [];
|
|
1727
|
+
let allRelations = [];
|
|
1728
|
+
try {
|
|
1729
|
+
allNodes = db.select().from(nexusSchema.nexusNodes).all();
|
|
1730
|
+
allRelations = db.select().from(nexusSchema.nexusRelations).all();
|
|
1731
|
+
}
|
|
1732
|
+
catch {
|
|
1733
|
+
// DB may be empty
|
|
1734
|
+
}
|
|
1735
|
+
// Filter by project if specified
|
|
1736
|
+
const nodes = projectFilter
|
|
1737
|
+
? allNodes.filter((n) => n['projectId'] === projectFilter)
|
|
1738
|
+
: allNodes;
|
|
1739
|
+
const relations = projectFilter
|
|
1740
|
+
? allRelations.filter((r) => r['projectId'] === projectFilter)
|
|
1741
|
+
: allRelations;
|
|
1742
|
+
let output = '';
|
|
1743
|
+
if (format === 'json') {
|
|
1744
|
+
output = JSON.stringify({
|
|
1745
|
+
nodes: nodes.map((n) => ({
|
|
1746
|
+
id: n['id'],
|
|
1747
|
+
kind: n['kind'],
|
|
1748
|
+
label: n['label'],
|
|
1749
|
+
name: n['name'],
|
|
1750
|
+
filePath: n['filePath'],
|
|
1751
|
+
language: n['language'],
|
|
1752
|
+
isExported: n['isExported'],
|
|
1753
|
+
startLine: n['startLine'],
|
|
1754
|
+
endLine: n['endLine'],
|
|
1755
|
+
projectId: n['projectId'],
|
|
1756
|
+
})),
|
|
1757
|
+
edges: relations.map((r) => ({
|
|
1758
|
+
id: r['id'],
|
|
1759
|
+
source: r['sourceId'],
|
|
1760
|
+
target: r['targetId'],
|
|
1761
|
+
type: r['type'],
|
|
1762
|
+
confidence: r['confidence'],
|
|
1763
|
+
reason: r['reason'],
|
|
1764
|
+
})),
|
|
1765
|
+
}, null, 2);
|
|
1766
|
+
}
|
|
1767
|
+
else if (format === 'gexf') {
|
|
1768
|
+
// GEXF format (Gephi standard)
|
|
1769
|
+
output = generateGexf(nodes, relations);
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
process.stderr.write(`[nexus] Error: Unknown format '${format}'. Supported: gexf, json\n`);
|
|
1773
|
+
process.exitCode = 1;
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
if (outputFile) {
|
|
1777
|
+
const { writeFileSync } = await import('node:fs');
|
|
1778
|
+
writeFileSync(outputFile, output, 'utf-8');
|
|
1779
|
+
process.stdout.write(`[nexus] Exported to ${outputFile} (${nodes.length} nodes, ${relations.length} edges)\n`);
|
|
1780
|
+
}
|
|
1781
|
+
else {
|
|
1782
|
+
process.stdout.write(output);
|
|
1783
|
+
if (!output.endsWith('\n'))
|
|
1784
|
+
process.stdout.write('\n');
|
|
1785
|
+
}
|
|
1786
|
+
const durationMs = Date.now() - startTime;
|
|
1787
|
+
if (outputFile) {
|
|
1788
|
+
process.stderr.write(`[nexus] Export completed in ${durationMs}ms\n`);
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
catch (err) {
|
|
1792
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1793
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1794
|
+
process.exitCode = 1;
|
|
1795
|
+
}
|
|
1796
|
+
},
|
|
1797
|
+
});
|
|
1798
|
+
/**
|
|
1799
|
+
* Compare NEXUS index state between two git commits.
|
|
1800
|
+
* @task T625
|
|
1801
|
+
*/
|
|
1802
|
+
const diffCommand = defineCommand({
|
|
1803
|
+
meta: {
|
|
1804
|
+
name: 'diff',
|
|
1805
|
+
description: 'Compare NEXUS index state between two git commits — shows new/removed relations and broken call chains',
|
|
1806
|
+
},
|
|
1807
|
+
args: {
|
|
1808
|
+
before: {
|
|
1809
|
+
type: 'string',
|
|
1810
|
+
description: 'Git SHA or ref for the "before" snapshot (default: HEAD~1)',
|
|
1811
|
+
},
|
|
1812
|
+
after: {
|
|
1813
|
+
type: 'string',
|
|
1814
|
+
description: 'Git SHA or ref for the "after" snapshot (default: HEAD)',
|
|
1815
|
+
default: 'HEAD',
|
|
1816
|
+
},
|
|
1817
|
+
path: { type: 'string', description: 'Repository directory to analyze (default: cwd)' },
|
|
1818
|
+
json: { type: 'boolean', description: 'Output result as JSON (LAFS envelope format)' },
|
|
1819
|
+
'project-id': {
|
|
1820
|
+
type: 'string',
|
|
1821
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
1822
|
+
},
|
|
1823
|
+
},
|
|
1824
|
+
async run({ args }) {
|
|
1825
|
+
const startTime = Date.now();
|
|
1826
|
+
const jsonOutput = !!args.json;
|
|
1827
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
1828
|
+
const projectIdOverride = args['project-id'];
|
|
1829
|
+
const beforeRef = args.before ?? 'HEAD~1';
|
|
1830
|
+
const afterRef = args.after ?? 'HEAD';
|
|
1831
|
+
if (!jsonOutput) {
|
|
1832
|
+
process.stderr.write(`[nexus] Diffing relations: ${beforeRef}..${afterRef} in ${repoPath}\n`);
|
|
1833
|
+
}
|
|
1834
|
+
const response = await dispatchRaw('query', 'nexus', 'diff', {
|
|
1835
|
+
repoPath,
|
|
1836
|
+
beforeRef,
|
|
1837
|
+
afterRef,
|
|
1838
|
+
projectId: projectIdOverride,
|
|
1839
|
+
});
|
|
1840
|
+
const durationMs = Date.now() - startTime;
|
|
1841
|
+
if (!response.success) {
|
|
1842
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1843
|
+
if (jsonOutput) {
|
|
1844
|
+
process.stdout.write(JSON.stringify({
|
|
1845
|
+
success: false,
|
|
1846
|
+
error: { code: response.error?.code ?? 'E_DIFF_FAILED', message: msg },
|
|
1847
|
+
meta: {
|
|
1848
|
+
operation: 'nexus.diff',
|
|
1849
|
+
duration_ms: durationMs,
|
|
1850
|
+
timestamp: new Date().toISOString(),
|
|
1851
|
+
},
|
|
1852
|
+
}, null, 2) + '\n');
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
process.stderr.write(`[nexus] Error running diff: ${msg}\n`);
|
|
1856
|
+
}
|
|
1857
|
+
process.exitCode = 1;
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
const result = response.data;
|
|
1861
|
+
if (jsonOutput) {
|
|
1862
|
+
process.stdout.write(JSON.stringify({
|
|
1863
|
+
success: true,
|
|
1864
|
+
data: result,
|
|
1865
|
+
meta: {
|
|
1866
|
+
operation: 'nexus.diff',
|
|
1867
|
+
duration_ms: durationMs,
|
|
1868
|
+
timestamp: new Date().toISOString(),
|
|
1869
|
+
},
|
|
1870
|
+
}, null, 2) + '\n');
|
|
1871
|
+
}
|
|
1872
|
+
else {
|
|
1873
|
+
process.stdout.write(`[nexus] Diff: ${result.beforeSha}..${result.afterSha}\n Changed files: ${result.changedFiles.length > 0 ? result.changedFiles.join(', ') : 'n/a'}\n Nodes: before=${result.nodesBefore} after=${result.nodesAfter} new=+${result.newNodes} removed=-${result.removedNodes}\n Relations: before=${result.relationsBefore} after=${result.relationsAfter} new=+${result.newRelations} removed=-${result.removedRelations}\n Health: ${result.healthStatus}\n`);
|
|
1874
|
+
if (result.regressions.length > 0) {
|
|
1875
|
+
process.stdout.write('\n REGRESSIONS:\n');
|
|
1876
|
+
for (const reg of result.regressions) {
|
|
1877
|
+
process.stdout.write(` - ${reg}\n`);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
process.stdout.write(' No regressions detected.\n');
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
},
|
|
1885
|
+
});
|
|
1886
|
+
/**
|
|
1887
|
+
* cleo nexus query — Execute recursive CTE queries against nexus.db
|
|
1888
|
+
*
|
|
1889
|
+
* Supports raw CTE syntax and 6 template aliases for common code intelligence patterns.
|
|
1890
|
+
* Results returned as markdown table.
|
|
1891
|
+
*
|
|
1892
|
+
* @task T1057
|
|
1893
|
+
*/
|
|
1894
|
+
const queryCommand = defineCommand({
|
|
1895
|
+
meta: {
|
|
1896
|
+
name: 'query',
|
|
1897
|
+
description: 'Execute recursive CTE queries against nexus.db',
|
|
1898
|
+
},
|
|
1899
|
+
args: {
|
|
1900
|
+
cte: {
|
|
1901
|
+
type: 'positional',
|
|
1902
|
+
description: 'CTE SQL or template alias (callers-of, callees-of, co-changed, co-cited, path-between, community-members)',
|
|
1903
|
+
required: true,
|
|
1904
|
+
},
|
|
1905
|
+
params: {
|
|
1906
|
+
type: 'string',
|
|
1907
|
+
description: 'Comma-separated parameters (e.g., "sym-id-1,sym-id-2")',
|
|
1908
|
+
},
|
|
1909
|
+
},
|
|
1910
|
+
async run({ args }) {
|
|
1911
|
+
const cteOrAlias = args.cte;
|
|
1912
|
+
const paramsStr = args.params || '';
|
|
1913
|
+
const params = paramsStr
|
|
1914
|
+
.split(',')
|
|
1915
|
+
.map((p) => p.trim())
|
|
1916
|
+
.filter(Boolean);
|
|
1917
|
+
const response = await dispatchRaw('query', 'nexus', 'query-cte', {
|
|
1918
|
+
cte: cteOrAlias,
|
|
1919
|
+
params,
|
|
1920
|
+
});
|
|
1921
|
+
if (!response.success) {
|
|
1922
|
+
const code = response.error?.code;
|
|
1923
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1924
|
+
const exitCode = code === 'E_INVALID_INPUT' ? 6 : 77;
|
|
1925
|
+
process.stderr.write(`[nexus] Error: ${msg}\n`);
|
|
1926
|
+
process.exitCode = exitCode;
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
const result = response.data;
|
|
1930
|
+
if (!result.success) {
|
|
1931
|
+
process.stderr.write(`[nexus] Query error: ${result.error ?? 'Unknown'}\n`);
|
|
1932
|
+
process.exitCode = 77;
|
|
1933
|
+
return;
|
|
1934
|
+
}
|
|
1935
|
+
// Format as markdown table using the DSL formatter
|
|
1936
|
+
const { formatCteResultAsMarkdown } = await import('@cleocode/core/nexus/query-dsl.js');
|
|
1937
|
+
const markdown = formatCteResultAsMarkdown(result);
|
|
1938
|
+
process.stdout.write(markdown + '\n');
|
|
1939
|
+
process.stdout.write(`\n[nexus] ${result.row_count} rows in ${result.execution_time_ms.toFixed(2)}ms\n`);
|
|
1940
|
+
},
|
|
1941
|
+
});
|
|
1942
|
+
/**
|
|
1943
|
+
* cleo nexus route-map — Display all routes with their handlers and dependencies.
|
|
1944
|
+
*/
|
|
1945
|
+
const routeMapCommand = defineCommand({
|
|
1946
|
+
meta: {
|
|
1947
|
+
name: 'route-map',
|
|
1948
|
+
description: 'Display all routes with their handlers and dependencies',
|
|
1949
|
+
},
|
|
1950
|
+
args: {
|
|
1951
|
+
path: {
|
|
1952
|
+
type: 'positional',
|
|
1953
|
+
description: 'Path to project directory (default: cwd)',
|
|
1954
|
+
required: false,
|
|
1955
|
+
},
|
|
1956
|
+
json: {
|
|
1957
|
+
type: 'boolean',
|
|
1958
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
1959
|
+
},
|
|
1960
|
+
'project-id': {
|
|
1961
|
+
type: 'string',
|
|
1962
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
1963
|
+
},
|
|
1964
|
+
},
|
|
1965
|
+
async run({ args }) {
|
|
1966
|
+
const startTime = Date.now();
|
|
1967
|
+
const jsonOutput = !!args.json;
|
|
1968
|
+
const projectIdOverride = args['project-id'];
|
|
1969
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
1970
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
1971
|
+
const response = await dispatchRaw('query', 'nexus', 'route-map', { projectId });
|
|
1972
|
+
const durationMs = Date.now() - startTime;
|
|
1973
|
+
if (!response.success) {
|
|
1974
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
1975
|
+
if (jsonOutput) {
|
|
1976
|
+
process.stdout.write(JSON.stringify({
|
|
1977
|
+
success: false,
|
|
1978
|
+
error: { code: response.error?.code ?? 'E_ROUTE_MAP_FAILED', message: msg },
|
|
1979
|
+
meta: {
|
|
1980
|
+
operation: 'nexus.route-map',
|
|
1981
|
+
duration_ms: durationMs,
|
|
1982
|
+
timestamp: new Date().toISOString(),
|
|
1983
|
+
},
|
|
1984
|
+
}, null, 2) + '\n');
|
|
1985
|
+
}
|
|
1986
|
+
else {
|
|
1987
|
+
process.stderr.write(`[nexus] Error running route-map: ${msg}\n`);
|
|
1988
|
+
}
|
|
1989
|
+
process.exitCode = 1;
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
const result = response.data;
|
|
1993
|
+
if (jsonOutput) {
|
|
1994
|
+
process.stdout.write(JSON.stringify({
|
|
1995
|
+
success: true,
|
|
1996
|
+
data: result,
|
|
1997
|
+
meta: {
|
|
1998
|
+
operation: 'nexus.route-map',
|
|
1999
|
+
duration_ms: durationMs,
|
|
2000
|
+
timestamp: new Date().toISOString(),
|
|
2001
|
+
},
|
|
2002
|
+
}, null, 2) + '\n');
|
|
2003
|
+
}
|
|
2004
|
+
else {
|
|
2005
|
+
if (result.routes.length === 0) {
|
|
2006
|
+
process.stdout.write(`[nexus] No routes found for project ${projectId}.\n Run 'cleo nexus analyze' first.\n`);
|
|
2007
|
+
}
|
|
2008
|
+
else {
|
|
2009
|
+
process.stdout.write(`[nexus] Route Map for project ${projectId} (${result.routes.length} total):\n\n`);
|
|
2010
|
+
process.stdout.write('| Route ID | Handler | Method | Path | Deps | Callers |\n');
|
|
2011
|
+
process.stdout.write('|----------|---------|--------|------|------|----------|\n');
|
|
2012
|
+
for (const route of result.routes) {
|
|
2013
|
+
const method = route.routeMeta['method'] ?? '—';
|
|
2014
|
+
const routePath = route.routeMeta['path'] ?? '—';
|
|
2015
|
+
const depCount = route.fetchedDeps.length;
|
|
2016
|
+
process.stdout.write(`| ${route.routeId} | ${route.handlerName} | ${method} | ${routePath} | ${depCount} | ${route.callerCount} |\n`);
|
|
2017
|
+
}
|
|
2018
|
+
process.stdout.write('\n');
|
|
2019
|
+
if (result.distinctDeps.length > 0) {
|
|
2020
|
+
process.stdout.write(`External dependencies: ${result.distinctDeps.join(', ')}\n`);
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
},
|
|
2025
|
+
});
|
|
2026
|
+
/**
|
|
2027
|
+
* cleo nexus shape-check — Check response shape compatibility for a route.
|
|
2028
|
+
*/
|
|
2029
|
+
const shapeCheckCommand = defineCommand({
|
|
2030
|
+
meta: {
|
|
2031
|
+
name: 'shape-check',
|
|
2032
|
+
description: 'Check response shape compatibility for a route handler',
|
|
2033
|
+
},
|
|
2034
|
+
args: {
|
|
2035
|
+
routeSymbol: {
|
|
2036
|
+
type: 'positional',
|
|
2037
|
+
description: 'Route symbol ID (format: <filePath>::<routeName>)',
|
|
2038
|
+
required: true,
|
|
2039
|
+
},
|
|
2040
|
+
path: {
|
|
2041
|
+
type: 'positional',
|
|
2042
|
+
description: 'Path to project directory (default: cwd)',
|
|
2043
|
+
required: false,
|
|
2044
|
+
},
|
|
2045
|
+
json: {
|
|
2046
|
+
type: 'boolean',
|
|
2047
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2048
|
+
},
|
|
2049
|
+
'project-id': {
|
|
2050
|
+
type: 'string',
|
|
2051
|
+
description: 'Override the project ID (default: auto-detected from path)',
|
|
2052
|
+
},
|
|
2053
|
+
},
|
|
2054
|
+
async run({ args }) {
|
|
2055
|
+
const startTime = Date.now();
|
|
2056
|
+
const routeSymbol = args.routeSymbol;
|
|
2057
|
+
const jsonOutput = !!args.json;
|
|
2058
|
+
const projectIdOverride = args['project-id'];
|
|
2059
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
2060
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
2061
|
+
const response = await dispatchRaw('query', 'nexus', 'shape-check', { routeSymbol, projectId });
|
|
2062
|
+
const durationMs = Date.now() - startTime;
|
|
2063
|
+
if (!response.success) {
|
|
2064
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2065
|
+
if (jsonOutput) {
|
|
2066
|
+
process.stdout.write(JSON.stringify({
|
|
2067
|
+
success: false,
|
|
2068
|
+
error: { code: response.error?.code ?? 'E_SHAPE_CHECK_FAILED', message: msg },
|
|
2069
|
+
meta: {
|
|
2070
|
+
operation: 'nexus.shape-check',
|
|
2071
|
+
duration_ms: durationMs,
|
|
2072
|
+
timestamp: new Date().toISOString(),
|
|
2073
|
+
},
|
|
2074
|
+
}, null, 2) + '\n');
|
|
2075
|
+
}
|
|
2076
|
+
else {
|
|
2077
|
+
process.stderr.write(`[nexus] Error running shape-check: ${msg}\n`);
|
|
2078
|
+
}
|
|
2079
|
+
process.exitCode = 1;
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
const result = response.data;
|
|
2083
|
+
if (jsonOutput) {
|
|
2084
|
+
process.stdout.write(JSON.stringify({
|
|
2085
|
+
success: true,
|
|
2086
|
+
data: result,
|
|
2087
|
+
meta: {
|
|
2088
|
+
operation: 'nexus.shape-check',
|
|
2089
|
+
duration_ms: durationMs,
|
|
2090
|
+
timestamp: new Date().toISOString(),
|
|
2091
|
+
},
|
|
2092
|
+
}, null, 2) + '\n');
|
|
2093
|
+
}
|
|
2094
|
+
else {
|
|
2095
|
+
process.stdout.write(`[nexus] Shape Check for route ${routeSymbol}\n\n`);
|
|
2096
|
+
process.stdout.write(`Handler: ${result.handlerId}\n`);
|
|
2097
|
+
process.stdout.write(`Declared Shape: ${result.declaredShape}\n`);
|
|
2098
|
+
process.stdout.write(`Overall Status: ${result.overallStatus}\n`);
|
|
2099
|
+
process.stdout.write(`Recommendation: ${result.recommendation}\n\n`);
|
|
2100
|
+
if (result.callers.length === 0) {
|
|
2101
|
+
process.stdout.write('No callers found.\n');
|
|
2102
|
+
}
|
|
2103
|
+
else {
|
|
2104
|
+
process.stdout.write(`Callers (${result.callers.length} total):\n`);
|
|
2105
|
+
process.stdout.write('| Caller | File | Expected Shape | Status |\n');
|
|
2106
|
+
process.stdout.write('|--------|------|---------------|---------|\n');
|
|
2107
|
+
for (const caller of result.callers) {
|
|
2108
|
+
process.stdout.write(`| ${caller.callerName} | ${caller.callerFile} | ${caller.expectedShape} | ${caller.status} |\n`);
|
|
2109
|
+
}
|
|
2110
|
+
if (result.callers.some((c) => c.status !== 'compatible')) {
|
|
2111
|
+
process.stdout.write('\nIncompatibilities:\n');
|
|
2112
|
+
for (const caller of result.callers) {
|
|
2113
|
+
if (caller.status !== 'compatible') {
|
|
2114
|
+
process.stdout.write(` - ${caller.callerName}: ${caller.diagnosis}\n`);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
},
|
|
2121
|
+
});
|
|
2122
|
+
/**
|
|
2123
|
+
* Root nexus command group — registers all nexus subcommands.
|
|
2124
|
+
*
|
|
2125
|
+
* Dispatches to nexus domain registry operations.
|
|
2126
|
+
* @task T4554
|
|
2127
|
+
*/
|
|
2128
|
+
// ---------------------------------------------------------------------------
|
|
2129
|
+
// Living Brain traversal commands (T1068)
|
|
2130
|
+
// ---------------------------------------------------------------------------
|
|
2131
|
+
/** cleo nexus full-context — show all 5-substrate context for a code symbol */
|
|
2132
|
+
const fullContextCommand = defineCommand({
|
|
2133
|
+
meta: {
|
|
2134
|
+
name: 'full-context',
|
|
2135
|
+
description: 'Show full Living Brain context for a symbol: NEXUS callers/callees, BRAIN memories, TASKS, sentient proposals, conduit threads',
|
|
2136
|
+
},
|
|
2137
|
+
args: {
|
|
2138
|
+
symbol: {
|
|
2139
|
+
type: 'positional',
|
|
2140
|
+
description: 'Symbol name or nexus node ID',
|
|
2141
|
+
required: true,
|
|
2142
|
+
},
|
|
2143
|
+
json: {
|
|
2144
|
+
type: 'boolean',
|
|
2145
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2146
|
+
},
|
|
2147
|
+
},
|
|
2148
|
+
async run({ args }) {
|
|
2149
|
+
const startTime = Date.now();
|
|
2150
|
+
const jsonOutput = !!args.json;
|
|
2151
|
+
const symbolId = args.symbol;
|
|
2152
|
+
const response = await dispatchRaw('query', 'nexus', 'full-context', { symbol: symbolId });
|
|
2153
|
+
if (!response.success) {
|
|
2154
|
+
process.stderr.write(`[nexus] Error running full-context: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
2155
|
+
process.exitCode = 1;
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
const result = response.data;
|
|
2159
|
+
const durationMs = Date.now() - startTime;
|
|
2160
|
+
if (jsonOutput) {
|
|
2161
|
+
process.stdout.write(JSON.stringify({
|
|
2162
|
+
success: true,
|
|
2163
|
+
data: result,
|
|
2164
|
+
meta: {
|
|
2165
|
+
operation: 'nexus.full-context',
|
|
2166
|
+
duration_ms: durationMs,
|
|
2167
|
+
timestamp: new Date().toISOString(),
|
|
2168
|
+
},
|
|
2169
|
+
}, null, 2) + '\n');
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
process.stdout.write(`\n## Living Brain: ${result.symbolId}\n\n`);
|
|
2173
|
+
process.stdout.write(`### NEXUS\n`);
|
|
2174
|
+
if (!result.nexus) {
|
|
2175
|
+
process.stdout.write(` (no nexus data — run 'cleo nexus analyze' first)\n`);
|
|
2176
|
+
}
|
|
2177
|
+
else {
|
|
2178
|
+
const n = result.nexus;
|
|
2179
|
+
process.stdout.write(` Kind: ${n.kind} File: ${n.filePath ?? '—'}\n`);
|
|
2180
|
+
process.stdout.write(` Callers (${n.callers.length}): ${n.callers
|
|
2181
|
+
.map((c) => c.name)
|
|
2182
|
+
.slice(0, 10)
|
|
2183
|
+
.join(', ') || '—'}\n`);
|
|
2184
|
+
process.stdout.write(` Callees (${n.callees.length}): ${n.callees
|
|
2185
|
+
.map((c) => c.name)
|
|
2186
|
+
.slice(0, 10)
|
|
2187
|
+
.join(', ') || '—'}\n`);
|
|
2188
|
+
process.stdout.write(` Plasticity: w=${result.plasticityWeight.totalWeight.toFixed(2)} edges=${result.plasticityWeight.edgeCount}\n`);
|
|
2189
|
+
}
|
|
2190
|
+
process.stdout.write(`\n### BRAIN memories (${result.brainMemories.length})\n`);
|
|
2191
|
+
for (const m of result.brainMemories.slice(0, 10)) {
|
|
2192
|
+
process.stdout.write(` [${m.nodeType}] ${m.label.slice(0, 80)} (edge=${m.edgeType} w=${m.weight.toFixed(2)})\n`);
|
|
2193
|
+
}
|
|
2194
|
+
if (result.brainMemories.length === 0)
|
|
2195
|
+
process.stdout.write(` (none)\n`);
|
|
2196
|
+
process.stdout.write(`\n### TASKS (${result.tasks.length})\n`);
|
|
2197
|
+
for (const t of result.tasks.slice(0, 10))
|
|
2198
|
+
process.stdout.write(` ${t.taskId} w=${t.weight.toFixed(2)}\n`);
|
|
2199
|
+
if (result.tasks.length === 0)
|
|
2200
|
+
process.stdout.write(` (none)\n`);
|
|
2201
|
+
process.stdout.write(`\n### SENTIENT proposals (${result.sentientProposals.length})\n`);
|
|
2202
|
+
for (const p of result.sentientProposals.slice(0, 5))
|
|
2203
|
+
process.stdout.write(` ${p.title.slice(0, 80)} (w=${p.weight.toFixed(2)})\n`);
|
|
2204
|
+
if (result.sentientProposals.length === 0)
|
|
2205
|
+
process.stdout.write(` (none)\n`);
|
|
2206
|
+
process.stdout.write(`\n### CONDUIT threads (${result.conduitThreads.length})\n`);
|
|
2207
|
+
for (const c of result.conduitThreads.slice(0, 5))
|
|
2208
|
+
process.stdout.write(` ${c.nodeId} w=${c.weight.toFixed(2)}\n`);
|
|
2209
|
+
if (result.conduitThreads.length === 0)
|
|
2210
|
+
process.stdout.write(` (none)\n`);
|
|
2211
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2212
|
+
},
|
|
2213
|
+
});
|
|
2214
|
+
/** cleo nexus task-footprint — show full code impact for a task */
|
|
2215
|
+
const taskFootprintCommand = defineCommand({
|
|
2216
|
+
meta: {
|
|
2217
|
+
name: 'task-footprint',
|
|
2218
|
+
description: 'Show full code impact of a task: files, symbols, blast radius, brain observations, decisions, risk tier',
|
|
2219
|
+
},
|
|
2220
|
+
args: {
|
|
2221
|
+
taskId: {
|
|
2222
|
+
type: 'positional',
|
|
2223
|
+
description: 'Task ID (e.g., T001)',
|
|
2224
|
+
required: true,
|
|
2225
|
+
},
|
|
2226
|
+
json: {
|
|
2227
|
+
type: 'boolean',
|
|
2228
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2229
|
+
},
|
|
2230
|
+
},
|
|
2231
|
+
async run({ args }) {
|
|
2232
|
+
const startTime = Date.now();
|
|
2233
|
+
const jsonOutput = !!args.json;
|
|
2234
|
+
const taskId = args.taskId;
|
|
2235
|
+
const response = await dispatchRaw('query', 'nexus', 'task-footprint', { taskId });
|
|
2236
|
+
if (!response.success) {
|
|
2237
|
+
process.stderr.write(`[nexus] Error running task-footprint: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
2238
|
+
process.exitCode = 1;
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
const result = response.data;
|
|
2242
|
+
const durationMs = Date.now() - startTime;
|
|
2243
|
+
if (jsonOutput) {
|
|
2244
|
+
process.stdout.write(JSON.stringify({
|
|
2245
|
+
success: true,
|
|
2246
|
+
data: result,
|
|
2247
|
+
meta: {
|
|
2248
|
+
operation: 'nexus.task-footprint',
|
|
2249
|
+
duration_ms: durationMs,
|
|
2250
|
+
timestamp: new Date().toISOString(),
|
|
2251
|
+
},
|
|
2252
|
+
}, null, 2) + '\n');
|
|
2253
|
+
return;
|
|
2254
|
+
}
|
|
2255
|
+
process.stdout.write(`\n## Task Code Impact: ${result.taskId}\n\n`);
|
|
2256
|
+
process.stdout.write(`**Risk Score**: ${result.riskScore}\n`);
|
|
2257
|
+
process.stdout.write(`**Files** (${result.files.length}): ${result.files.slice(0, 10).join(', ') || '—'}\n\n`);
|
|
2258
|
+
process.stdout.write(`### Symbols (${result.symbols.length})\n`);
|
|
2259
|
+
for (const s of result.symbols.slice(0, 20)) {
|
|
2260
|
+
process.stdout.write(` [${s.riskLevel}] ${s.label} (${s.kind}) d1=${s.directCallers} total=${s.totalAffected}\n`);
|
|
2261
|
+
}
|
|
2262
|
+
if (result.symbols.length === 0)
|
|
2263
|
+
process.stdout.write(` (none — run 'cleo nexus analyze' or link task to symbols first)\n`);
|
|
2264
|
+
process.stdout.write(`\n### Blast Radius\n`);
|
|
2265
|
+
process.stdout.write(` analyzed=${result.blastRadius.symbolsAnalyzed} total_affected=${result.blastRadius.totalAffected} max_risk=${result.blastRadius.maxRisk}\n`);
|
|
2266
|
+
process.stdout.write(`\n### Brain Observations (${result.brainObservations.length})\n`);
|
|
2267
|
+
for (const o of result.brainObservations.slice(0, 5))
|
|
2268
|
+
process.stdout.write(` [${o.nodeType}] ${o.label.slice(0, 80)}\n`);
|
|
2269
|
+
process.stdout.write(`\n### Decisions (${result.decisions.length})\n`);
|
|
2270
|
+
for (const d of result.decisions.slice(0, 5))
|
|
2271
|
+
process.stdout.write(` [${d.linkType}] ${d.decision.slice(0, 80)}\n`);
|
|
2272
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2273
|
+
},
|
|
2274
|
+
});
|
|
2275
|
+
/** cleo nexus brain-anchors — show code anchors for a brain memory entry */
|
|
2276
|
+
const brainAnchorsCommand = defineCommand({
|
|
2277
|
+
meta: {
|
|
2278
|
+
name: 'brain-anchors',
|
|
2279
|
+
description: 'Show code anchors for a brain memory entry: linked nexus nodes, tasks that touched them, plasticity signal',
|
|
2280
|
+
},
|
|
2281
|
+
args: {
|
|
2282
|
+
entryId: {
|
|
2283
|
+
type: 'positional',
|
|
2284
|
+
description: 'Brain entry node ID (e.g., observation:abc123)',
|
|
2285
|
+
required: true,
|
|
2286
|
+
},
|
|
2287
|
+
json: {
|
|
2288
|
+
type: 'boolean',
|
|
2289
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2290
|
+
},
|
|
2291
|
+
},
|
|
2292
|
+
async run({ args }) {
|
|
2293
|
+
const startTime = Date.now();
|
|
2294
|
+
const jsonOutput = !!args.json;
|
|
2295
|
+
const entryId = args.entryId;
|
|
2296
|
+
const response = await dispatchRaw('query', 'nexus', 'brain-anchors', { entryId });
|
|
2297
|
+
if (!response.success) {
|
|
2298
|
+
process.stderr.write(`[nexus] Error running brain-anchors: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
2299
|
+
process.exitCode = 1;
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
const result = response.data;
|
|
2303
|
+
const durationMs = Date.now() - startTime;
|
|
2304
|
+
if (jsonOutput) {
|
|
2305
|
+
process.stdout.write(JSON.stringify({
|
|
2306
|
+
success: true,
|
|
2307
|
+
data: result,
|
|
2308
|
+
meta: {
|
|
2309
|
+
operation: 'nexus.brain-anchors',
|
|
2310
|
+
duration_ms: durationMs,
|
|
2311
|
+
timestamp: new Date().toISOString(),
|
|
2312
|
+
},
|
|
2313
|
+
}, null, 2) + '\n');
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
process.stdout.write(`\n## Brain Code Anchors: ${result.entryId}\n\n`);
|
|
2317
|
+
process.stdout.write(`**Plasticity Signal**: ${result.plasticitySignal.toFixed(2)}\n\n`);
|
|
2318
|
+
process.stdout.write(`### Nexus Nodes (${result.nexusNodes.length})\n`);
|
|
2319
|
+
for (const n of result.nexusNodes.slice(0, 20)) {
|
|
2320
|
+
process.stdout.write(` [${n.kind}] ${n.label} file=${n.filePath ?? '—'} edge=${n.edgeType} w=${n.weight.toFixed(2)}\n`);
|
|
2321
|
+
}
|
|
2322
|
+
if (result.nexusNodes.length === 0)
|
|
2323
|
+
process.stdout.write(` (none)\n`);
|
|
2324
|
+
process.stdout.write(`\n### Tasks for Nodes (${result.tasksForNodes.length} nodes with task links)\n`);
|
|
2325
|
+
for (const entry of result.tasksForNodes.slice(0, 10)) {
|
|
2326
|
+
const taskList = entry.tasks.map((t) => t.taskId).join(', ');
|
|
2327
|
+
process.stdout.write(` ${entry.nexusNodeId}: ${taskList}\n`);
|
|
2328
|
+
}
|
|
2329
|
+
if (result.tasksForNodes.length === 0)
|
|
2330
|
+
process.stdout.write(` (none)\n`);
|
|
2331
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2332
|
+
},
|
|
2333
|
+
});
|
|
2334
|
+
// ---------------------------------------------------------------------------
|
|
2335
|
+
// Extended Code Reasoning commands (T1069)
|
|
2336
|
+
// ---------------------------------------------------------------------------
|
|
2337
|
+
/** cleo nexus why <symbol> — trace why a code symbol is structured this way */
|
|
2338
|
+
const whyCommand = defineCommand({
|
|
2339
|
+
meta: {
|
|
2340
|
+
name: 'why',
|
|
2341
|
+
description: 'Trace why a code symbol is structured this way: walks BRAIN decisions, observations, and tasks via code_reference+documents+applies_to edges',
|
|
2342
|
+
},
|
|
2343
|
+
args: {
|
|
2344
|
+
symbol: {
|
|
2345
|
+
type: 'positional',
|
|
2346
|
+
description: 'Symbol name or nexus node ID to trace',
|
|
2347
|
+
required: true,
|
|
2348
|
+
},
|
|
2349
|
+
json: {
|
|
2350
|
+
type: 'boolean',
|
|
2351
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2352
|
+
},
|
|
2353
|
+
},
|
|
2354
|
+
async run({ args }) {
|
|
2355
|
+
const startTime = Date.now();
|
|
2356
|
+
const jsonOutput = !!args.json;
|
|
2357
|
+
const symbolId = args.symbol;
|
|
2358
|
+
const response = await dispatchRaw('query', 'nexus', 'why', { symbol: symbolId });
|
|
2359
|
+
if (!response.success) {
|
|
2360
|
+
process.stderr.write(`[nexus] Error running why: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
2361
|
+
process.exitCode = 1;
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
const result = response.data;
|
|
2365
|
+
const durationMs = Date.now() - startTime;
|
|
2366
|
+
if (jsonOutput) {
|
|
2367
|
+
process.stdout.write(JSON.stringify({
|
|
2368
|
+
success: true,
|
|
2369
|
+
data: result,
|
|
2370
|
+
meta: {
|
|
2371
|
+
operation: 'nexus.why',
|
|
2372
|
+
duration_ms: durationMs,
|
|
2373
|
+
timestamp: new Date().toISOString(),
|
|
2374
|
+
},
|
|
2375
|
+
}, null, 2) + '\n');
|
|
2376
|
+
return;
|
|
2377
|
+
}
|
|
2378
|
+
process.stdout.write(`\n## Code Reasoning: ${result.symbolId}\n\n`);
|
|
2379
|
+
process.stdout.write(`**Narrative**: ${result.narrative}\n\n`);
|
|
2380
|
+
process.stdout.write(`### Trace Chain (${result.chain.length} steps)\n`);
|
|
2381
|
+
if (result.chain.length === 0) {
|
|
2382
|
+
process.stdout.write(` (no trace — run 'cleo nexus analyze' and 'cleo memory code-links' first)\n`);
|
|
2383
|
+
}
|
|
2384
|
+
else {
|
|
2385
|
+
for (const step of result.chain) {
|
|
2386
|
+
const refsStr = step.refs.length > 0 ? ` refs=[${step.refs.join(', ')}]` : '';
|
|
2387
|
+
process.stdout.write(` [${step.type}] ${step.id}: ${step.title.slice(0, 80)}${refsStr}\n`);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2391
|
+
},
|
|
2392
|
+
});
|
|
2393
|
+
/** cleo nexus impact-full <symbol> — merged structural + task + brain impact report */
|
|
2394
|
+
const impactFullCommand = defineCommand({
|
|
2395
|
+
meta: {
|
|
2396
|
+
name: 'impact-full',
|
|
2397
|
+
description: 'Full merged impact report for a code symbol: structural blast radius + open tasks + brain risk notes',
|
|
2398
|
+
},
|
|
2399
|
+
args: {
|
|
2400
|
+
symbol: {
|
|
2401
|
+
type: 'positional',
|
|
2402
|
+
description: 'Symbol name or nexus node ID to analyze',
|
|
2403
|
+
required: true,
|
|
2404
|
+
},
|
|
2405
|
+
json: {
|
|
2406
|
+
type: 'boolean',
|
|
2407
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2408
|
+
},
|
|
2409
|
+
},
|
|
2410
|
+
async run({ args }) {
|
|
2411
|
+
const startTime = Date.now();
|
|
2412
|
+
const jsonOutput = !!args.json;
|
|
2413
|
+
const symbolId = args.symbol;
|
|
2414
|
+
const response = await dispatchRaw('query', 'nexus', 'impact-full', { symbol: symbolId });
|
|
2415
|
+
if (!response.success) {
|
|
2416
|
+
process.stderr.write(`[nexus] Error running impact-full: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
2417
|
+
process.exitCode = 1;
|
|
2418
|
+
return;
|
|
2419
|
+
}
|
|
2420
|
+
const result = response.data;
|
|
2421
|
+
const durationMs = Date.now() - startTime;
|
|
2422
|
+
if (jsonOutput) {
|
|
2423
|
+
process.stdout.write(JSON.stringify({
|
|
2424
|
+
success: true,
|
|
2425
|
+
data: result,
|
|
2426
|
+
meta: {
|
|
2427
|
+
operation: 'nexus.impact-full',
|
|
2428
|
+
duration_ms: durationMs,
|
|
2429
|
+
timestamp: new Date().toISOString(),
|
|
2430
|
+
},
|
|
2431
|
+
}, null, 2) + '\n');
|
|
2432
|
+
return;
|
|
2433
|
+
}
|
|
2434
|
+
process.stdout.write(`\n## Full Impact: ${result.symbolId}\n\n`);
|
|
2435
|
+
process.stdout.write(`**Merged Risk Score**: ${result.mergedRiskScore}\n`);
|
|
2436
|
+
process.stdout.write(`**Narrative**: ${result.narrative}\n\n`);
|
|
2437
|
+
process.stdout.write(`### Structural Blast Radius\n`);
|
|
2438
|
+
process.stdout.write(` d=1 (will break)=${result.structural.directCallers}` +
|
|
2439
|
+
` d=2 (likely affected)=${result.structural.likelyAffected}` +
|
|
2440
|
+
` d=3 (may need testing)=${result.structural.mayNeedTesting}` +
|
|
2441
|
+
` total=${result.structural.totalAffected}` +
|
|
2442
|
+
` risk=${result.structural.riskLevel}\n`);
|
|
2443
|
+
process.stdout.write(`\n### Open Tasks (${result.openTasks.length})\n`);
|
|
2444
|
+
for (const t of result.openTasks.slice(0, 10)) {
|
|
2445
|
+
process.stdout.write(` ${t.taskId} ${t.label.slice(0, 60)} w=${t.weight.toFixed(2)}\n`);
|
|
2446
|
+
}
|
|
2447
|
+
if (result.openTasks.length === 0)
|
|
2448
|
+
process.stdout.write(` (none)\n`);
|
|
2449
|
+
process.stdout.write(`\n### Brain Risk Notes (${result.brainRiskNotes.length})\n`);
|
|
2450
|
+
for (const n of result.brainRiskNotes.slice(0, 10)) {
|
|
2451
|
+
process.stdout.write(` [${n.nodeType}] ${n.label.slice(0, 70)} edge=${n.edgeType} w=${n.weight.toFixed(2)}\n`);
|
|
2452
|
+
}
|
|
2453
|
+
if (result.brainRiskNotes.length === 0)
|
|
2454
|
+
process.stdout.write(` (none)\n`);
|
|
2455
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2456
|
+
},
|
|
2457
|
+
});
|
|
2458
|
+
// ---------------------------------------------------------------------------
|
|
2459
|
+
// T1071 — conduit-scan: link conduit messages to nexus symbols
|
|
2460
|
+
// ---------------------------------------------------------------------------
|
|
2461
|
+
/**
|
|
2462
|
+
* cleo nexus conduit-scan — Scan conduit messages and link them to nexus symbols.
|
|
2463
|
+
*
|
|
2464
|
+
* Writes `conduit_mentions_symbol` edges to brain_page_edges (idempotent).
|
|
2465
|
+
* Gracefully no-ops when conduit.db or nexus.db is absent.
|
|
2466
|
+
*
|
|
2467
|
+
* @task T1071
|
|
2468
|
+
* @epic T1042
|
|
2469
|
+
*/
|
|
2470
|
+
const conduitScanCommand = defineCommand({
|
|
2471
|
+
meta: {
|
|
2472
|
+
name: 'conduit-scan',
|
|
2473
|
+
description: 'Scan conduit messages for symbol mentions and link them to nexus nodes (conduit_mentions_symbol edges)',
|
|
2474
|
+
},
|
|
2475
|
+
args: {
|
|
2476
|
+
json: {
|
|
2477
|
+
type: 'boolean',
|
|
2478
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2479
|
+
},
|
|
2480
|
+
},
|
|
2481
|
+
async run({ args }) {
|
|
2482
|
+
const startTime = Date.now();
|
|
2483
|
+
const jsonOutput = !!args.json;
|
|
2484
|
+
const response = await dispatchRaw('mutate', 'nexus', 'conduit-scan', {});
|
|
2485
|
+
const durationMs = Date.now() - startTime;
|
|
2486
|
+
if (!response.success) {
|
|
2487
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2488
|
+
if (jsonOutput) {
|
|
2489
|
+
process.stdout.write(JSON.stringify({
|
|
2490
|
+
success: false,
|
|
2491
|
+
error: { code: response.error?.code ?? 'E_CONDUIT_SCAN_FAILED', message: msg },
|
|
2492
|
+
meta: {
|
|
2493
|
+
operation: 'nexus.conduit-scan',
|
|
2494
|
+
duration_ms: durationMs,
|
|
2495
|
+
timestamp: new Date().toISOString(),
|
|
2496
|
+
},
|
|
2497
|
+
}, null, 2) + '\n');
|
|
2498
|
+
}
|
|
2499
|
+
else {
|
|
2500
|
+
process.stderr.write(`[nexus] Error running conduit-scan: ${msg}\n`);
|
|
2501
|
+
}
|
|
2502
|
+
process.exitCode = 1;
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
const result = response.data;
|
|
2506
|
+
if (jsonOutput) {
|
|
2507
|
+
process.stdout.write(JSON.stringify({
|
|
2508
|
+
success: true,
|
|
2509
|
+
data: result,
|
|
2510
|
+
meta: {
|
|
2511
|
+
operation: 'nexus.conduit-scan',
|
|
2512
|
+
duration_ms: durationMs,
|
|
2513
|
+
timestamp: new Date().toISOString(),
|
|
2514
|
+
},
|
|
2515
|
+
}, null, 2) + '\n');
|
|
2516
|
+
}
|
|
2517
|
+
else {
|
|
2518
|
+
process.stdout.write(`[nexus] conduit-scan complete: scanned=${result.scanned} linked=${result.linked} (${durationMs}ms)\n`);
|
|
2519
|
+
}
|
|
2520
|
+
},
|
|
2521
|
+
});
|
|
2522
|
+
// ---------------------------------------------------------------------------
|
|
2523
|
+
// T1067 — task-symbols: show symbols touched by a task
|
|
2524
|
+
// ---------------------------------------------------------------------------
|
|
2525
|
+
/**
|
|
2526
|
+
* cleo nexus task-symbols <taskId> — Show code symbols touched by a task.
|
|
2527
|
+
*
|
|
2528
|
+
* Forward-lookup (task → symbols) via task_touches_symbol edges.
|
|
2529
|
+
*
|
|
2530
|
+
* @task T1067
|
|
2531
|
+
* @epic T1042
|
|
2532
|
+
*/
|
|
2533
|
+
const taskSymbolsCommand = defineCommand({
|
|
2534
|
+
meta: {
|
|
2535
|
+
name: 'task-symbols',
|
|
2536
|
+
description: 'Show code symbols touched by a task (task_touches_symbol forward-lookup)',
|
|
2537
|
+
},
|
|
2538
|
+
args: {
|
|
2539
|
+
taskId: {
|
|
2540
|
+
type: 'positional',
|
|
2541
|
+
description: 'Task ID (e.g., T001)',
|
|
2542
|
+
required: true,
|
|
2543
|
+
},
|
|
2544
|
+
json: {
|
|
2545
|
+
type: 'boolean',
|
|
2546
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2547
|
+
},
|
|
2548
|
+
},
|
|
2549
|
+
async run({ args }) {
|
|
2550
|
+
const startTime = Date.now();
|
|
2551
|
+
const jsonOutput = !!args.json;
|
|
2552
|
+
const taskId = args.taskId;
|
|
2553
|
+
const response = await dispatchRaw('query', 'nexus', 'task-symbols', { taskId });
|
|
2554
|
+
const durationMs = Date.now() - startTime;
|
|
2555
|
+
if (!response.success) {
|
|
2556
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2557
|
+
if (jsonOutput) {
|
|
2558
|
+
process.stdout.write(JSON.stringify({
|
|
2559
|
+
success: false,
|
|
2560
|
+
error: { code: response.error?.code ?? 'E_TASK_SYMBOLS_FAILED', message: msg },
|
|
2561
|
+
meta: {
|
|
2562
|
+
operation: 'nexus.task-symbols',
|
|
2563
|
+
duration_ms: durationMs,
|
|
2564
|
+
timestamp: new Date().toISOString(),
|
|
2565
|
+
},
|
|
2566
|
+
}, null, 2) + '\n');
|
|
2567
|
+
}
|
|
2568
|
+
else {
|
|
2569
|
+
process.stderr.write(`[nexus] Error running task-symbols: ${msg}\n`);
|
|
2570
|
+
}
|
|
2571
|
+
process.exitCode = 1;
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
2574
|
+
const data = response.data;
|
|
2575
|
+
const { symbols } = data;
|
|
2576
|
+
if (jsonOutput) {
|
|
2577
|
+
process.stdout.write(JSON.stringify({
|
|
2578
|
+
success: true,
|
|
2579
|
+
data: { taskId, count: symbols.length, symbols },
|
|
2580
|
+
meta: {
|
|
2581
|
+
operation: 'nexus.task-symbols',
|
|
2582
|
+
duration_ms: durationMs,
|
|
2583
|
+
timestamp: new Date().toISOString(),
|
|
2584
|
+
},
|
|
2585
|
+
}, null, 2) + '\n');
|
|
2586
|
+
}
|
|
2587
|
+
else {
|
|
2588
|
+
if (symbols.length === 0) {
|
|
2589
|
+
process.stdout.write(`[nexus] No symbols found for task ${taskId}.\n Run 'cleo nexus analyze' and ensure git history is available.\n`);
|
|
2590
|
+
}
|
|
2591
|
+
else {
|
|
2592
|
+
process.stdout.write(`[nexus] Symbols touched by ${taskId} (${symbols.length} total):\n\n`);
|
|
2593
|
+
for (const s of symbols) {
|
|
2594
|
+
process.stdout.write(` [${s.kind.padEnd(12)}] ${s.label.padEnd(50)} w=${s.weight.toFixed(2)} via=${s.matchStrategy}\n`);
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2598
|
+
}
|
|
2599
|
+
},
|
|
2600
|
+
});
|
|
2601
|
+
// ---------------------------------------------------------------------------
|
|
2602
|
+
// T1058 — search-code: BM25 code symbol search against nexus.db
|
|
2603
|
+
// ---------------------------------------------------------------------------
|
|
2604
|
+
/**
|
|
2605
|
+
* cleo nexus search-code <query> — BM25 search of code symbols in nexus.db.
|
|
2606
|
+
*
|
|
2607
|
+
* Uses the same BM25 index as the augment hook. Returns symbol names, kinds,
|
|
2608
|
+
* file paths, and relevance scores.
|
|
2609
|
+
*
|
|
2610
|
+
* @task T1058
|
|
2611
|
+
* @epic T1042
|
|
2612
|
+
*/
|
|
2613
|
+
const searchCodeCommand = defineCommand({
|
|
2614
|
+
meta: {
|
|
2615
|
+
name: 'search-code',
|
|
2616
|
+
description: 'BM25 search of code symbols in nexus.db (augment BM25 index)',
|
|
2617
|
+
},
|
|
2618
|
+
args: {
|
|
2619
|
+
query: {
|
|
2620
|
+
type: 'positional',
|
|
2621
|
+
description: 'Search query (symbol name, file pattern, or keyword)',
|
|
2622
|
+
required: true,
|
|
2623
|
+
},
|
|
2624
|
+
limit: {
|
|
2625
|
+
type: 'string',
|
|
2626
|
+
description: 'Max results (default: 10)',
|
|
2627
|
+
default: '10',
|
|
2628
|
+
},
|
|
2629
|
+
json: {
|
|
2630
|
+
type: 'boolean',
|
|
2631
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2632
|
+
},
|
|
2633
|
+
},
|
|
2634
|
+
async run({ args }) {
|
|
2635
|
+
const startTime = Date.now();
|
|
2636
|
+
const jsonOutput = !!args.json;
|
|
2637
|
+
const query = args.query;
|
|
2638
|
+
const limit = parseInt(args.limit, 10) || 10;
|
|
2639
|
+
await dispatchFromCli('query', 'nexus', 'augment', { pattern: query, limit }, { command: 'nexus' });
|
|
2640
|
+
const durationMs = Date.now() - startTime;
|
|
2641
|
+
if (!jsonOutput) {
|
|
2642
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2643
|
+
}
|
|
2644
|
+
},
|
|
2645
|
+
});
|
|
2646
|
+
// ---------------------------------------------------------------------------
|
|
2647
|
+
// T1065 — contracts: contract extraction and compatibility commands
|
|
2648
|
+
// ---------------------------------------------------------------------------
|
|
2649
|
+
/** cleo nexus contracts sync — extract and store contracts from current project */
|
|
2650
|
+
const contractsSyncCommand = defineCommand({
|
|
2651
|
+
meta: {
|
|
2652
|
+
name: 'sync',
|
|
2653
|
+
description: 'Extract contracts (HTTP/gRPC/topic) from the current project and store them',
|
|
2654
|
+
},
|
|
2655
|
+
args: {
|
|
2656
|
+
path: {
|
|
2657
|
+
type: 'positional',
|
|
2658
|
+
description: 'Path to project directory (default: cwd)',
|
|
2659
|
+
required: false,
|
|
2660
|
+
},
|
|
2661
|
+
json: {
|
|
2662
|
+
type: 'boolean',
|
|
2663
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2664
|
+
},
|
|
2665
|
+
'project-id': {
|
|
2666
|
+
type: 'string',
|
|
2667
|
+
description: 'Override the project ID (default: auto-detected)',
|
|
2668
|
+
},
|
|
2669
|
+
},
|
|
2670
|
+
async run({ args }) {
|
|
2671
|
+
const startTime = Date.now();
|
|
2672
|
+
const jsonOutput = !!args.json;
|
|
2673
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
2674
|
+
const projectIdOverride = args['project-id'];
|
|
2675
|
+
const projectId = projectIdOverride ?? Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
2676
|
+
const response = await dispatchRaw('mutate', 'nexus', 'contracts-sync', {
|
|
2677
|
+
projectId,
|
|
2678
|
+
repoPath,
|
|
2679
|
+
});
|
|
2680
|
+
const durationMs = Date.now() - startTime;
|
|
2681
|
+
if (!response.success) {
|
|
2682
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2683
|
+
if (jsonOutput) {
|
|
2684
|
+
process.stdout.write(JSON.stringify({
|
|
2685
|
+
success: false,
|
|
2686
|
+
error: { code: response.error?.code ?? 'E_CONTRACTS_SYNC_FAILED', message: msg },
|
|
2687
|
+
meta: {
|
|
2688
|
+
operation: 'nexus.contracts.sync',
|
|
2689
|
+
duration_ms: durationMs,
|
|
2690
|
+
timestamp: new Date().toISOString(),
|
|
2691
|
+
},
|
|
2692
|
+
}, null, 2) + '\n');
|
|
2693
|
+
}
|
|
2694
|
+
else {
|
|
2695
|
+
process.stderr.write(`[nexus] Error running contracts sync: ${msg}\n`);
|
|
2696
|
+
}
|
|
2697
|
+
process.exitCode = 1;
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
const result = response.data;
|
|
2701
|
+
if (jsonOutput) {
|
|
2702
|
+
process.stdout.write(JSON.stringify({
|
|
2703
|
+
success: true,
|
|
2704
|
+
data: result,
|
|
2705
|
+
meta: {
|
|
2706
|
+
operation: 'nexus.contracts.sync',
|
|
2707
|
+
duration_ms: durationMs,
|
|
2708
|
+
timestamp: new Date().toISOString(),
|
|
2709
|
+
},
|
|
2710
|
+
}, null, 2) + '\n');
|
|
2711
|
+
}
|
|
2712
|
+
else {
|
|
2713
|
+
process.stdout.write(`[nexus] Contracts extracted from ${projectId}:\n` +
|
|
2714
|
+
` HTTP: ${result.http}\n` +
|
|
2715
|
+
` gRPC: ${result.grpc}\n` +
|
|
2716
|
+
` Topic: ${result.topic}\n` +
|
|
2717
|
+
` Total: ${result.totalCount}\n` +
|
|
2718
|
+
` (${durationMs}ms)\n`);
|
|
2719
|
+
}
|
|
2720
|
+
},
|
|
2721
|
+
});
|
|
2722
|
+
/** cleo nexus contracts show — show contract compatibility between two projects */
|
|
2723
|
+
const contractsShowCommand = defineCommand({
|
|
2724
|
+
meta: {
|
|
2725
|
+
name: 'show',
|
|
2726
|
+
description: 'Show contract compatibility matrix between two registered projects',
|
|
2727
|
+
},
|
|
2728
|
+
args: {
|
|
2729
|
+
'project-a': {
|
|
2730
|
+
type: 'string',
|
|
2731
|
+
description: 'First project name or ID',
|
|
2732
|
+
required: true,
|
|
2733
|
+
},
|
|
2734
|
+
'project-b': {
|
|
2735
|
+
type: 'string',
|
|
2736
|
+
description: 'Second project name or ID',
|
|
2737
|
+
required: true,
|
|
2738
|
+
},
|
|
2739
|
+
json: {
|
|
2740
|
+
type: 'boolean',
|
|
2741
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2742
|
+
},
|
|
2743
|
+
},
|
|
2744
|
+
async run({ args }) {
|
|
2745
|
+
const startTime = Date.now();
|
|
2746
|
+
const jsonOutput = !!args.json;
|
|
2747
|
+
const projectA = args['project-a'];
|
|
2748
|
+
const projectB = args['project-b'];
|
|
2749
|
+
const response = await dispatchRaw('query', 'nexus', 'contracts-show', { projectA, projectB });
|
|
2750
|
+
const durationMs = Date.now() - startTime;
|
|
2751
|
+
if (!response.success) {
|
|
2752
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2753
|
+
if (jsonOutput) {
|
|
2754
|
+
process.stdout.write(JSON.stringify({
|
|
2755
|
+
success: false,
|
|
2756
|
+
error: { code: response.error?.code ?? 'E_CONTRACTS_SHOW_FAILED', message: msg },
|
|
2757
|
+
meta: {
|
|
2758
|
+
operation: 'nexus.contracts.show',
|
|
2759
|
+
duration_ms: durationMs,
|
|
2760
|
+
timestamp: new Date().toISOString(),
|
|
2761
|
+
},
|
|
2762
|
+
}, null, 2) + '\n');
|
|
2763
|
+
}
|
|
2764
|
+
else {
|
|
2765
|
+
process.stderr.write(`[nexus] Error running contracts show: ${msg}\n`);
|
|
2766
|
+
}
|
|
2767
|
+
process.exitCode = 1;
|
|
2768
|
+
return;
|
|
2769
|
+
}
|
|
2770
|
+
const result = response.data;
|
|
2771
|
+
if (jsonOutput) {
|
|
2772
|
+
process.stdout.write(JSON.stringify({
|
|
2773
|
+
success: true,
|
|
2774
|
+
data: result,
|
|
2775
|
+
meta: {
|
|
2776
|
+
operation: 'nexus.contracts.show',
|
|
2777
|
+
duration_ms: durationMs,
|
|
2778
|
+
timestamp: new Date().toISOString(),
|
|
2779
|
+
},
|
|
2780
|
+
}, null, 2) + '\n');
|
|
2781
|
+
}
|
|
2782
|
+
else {
|
|
2783
|
+
if (result.matches.length === 0) {
|
|
2784
|
+
process.stdout.write(`[nexus] No contract matches found between ${projectA} and ${projectB}.\n Run 'cleo nexus contracts sync' on both projects first.\n`);
|
|
2785
|
+
}
|
|
2786
|
+
else {
|
|
2787
|
+
process.stdout.write(`[nexus] Contract compatibility: ${projectA} ↔ ${projectB}\n Compatible: ${result.compatibleCount} Incompatible: ${result.incompatibleCount} Partial: ${result.partialCount}\n Overall: ${result.overallCompatibility}%\n\n`);
|
|
2788
|
+
for (const m of result.matches.slice(0, 20)) {
|
|
2789
|
+
process.stdout.write(` [${m.compatibility.toUpperCase().padEnd(12)}] ${m.contractA.id} ↔ ${m.contractB.id} score=${m.score.toFixed(2)}\n`);
|
|
2790
|
+
}
|
|
2791
|
+
if (result.matches.length > 20) {
|
|
2792
|
+
process.stdout.write(` (showing 20 of ${result.matches.length} matches)\n`);
|
|
2793
|
+
}
|
|
2794
|
+
}
|
|
2795
|
+
process.stdout.write(`\n(${durationMs}ms)\n`);
|
|
2796
|
+
}
|
|
2797
|
+
},
|
|
2798
|
+
});
|
|
2799
|
+
/** cleo nexus contracts link-tasks — link contracts to tasks via task_touches_symbol edges */
|
|
2800
|
+
const contractsLinkTasksCommand = defineCommand({
|
|
2801
|
+
meta: {
|
|
2802
|
+
name: 'link-tasks',
|
|
2803
|
+
description: 'Link extracted contracts to tasks that touch their source symbols',
|
|
2804
|
+
},
|
|
2805
|
+
args: {
|
|
2806
|
+
path: {
|
|
2807
|
+
type: 'positional',
|
|
2808
|
+
description: 'Path to project directory (default: cwd)',
|
|
2809
|
+
required: false,
|
|
2810
|
+
},
|
|
2811
|
+
json: {
|
|
2812
|
+
type: 'boolean',
|
|
2813
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2814
|
+
},
|
|
2815
|
+
},
|
|
2816
|
+
async run({ args }) {
|
|
2817
|
+
const startTime = Date.now();
|
|
2818
|
+
const jsonOutput = !!args.json;
|
|
2819
|
+
const repoPath = args.path ? path.resolve(args.path) : process.cwd();
|
|
2820
|
+
const projectId = Buffer.from(repoPath).toString('base64url').slice(0, 32);
|
|
2821
|
+
const response = await dispatchRaw('mutate', 'nexus', 'contracts-link-tasks', {
|
|
2822
|
+
projectId,
|
|
2823
|
+
repoPath,
|
|
2824
|
+
});
|
|
2825
|
+
const durationMs = Date.now() - startTime;
|
|
2826
|
+
if (!response.success) {
|
|
2827
|
+
const msg = response.error?.message ?? 'Unknown error';
|
|
2828
|
+
if (jsonOutput) {
|
|
2829
|
+
process.stdout.write(JSON.stringify({
|
|
2830
|
+
success: false,
|
|
2831
|
+
error: { code: response.error?.code ?? 'E_CONTRACTS_LINK_FAILED', message: msg },
|
|
2832
|
+
meta: {
|
|
2833
|
+
operation: 'nexus.contracts.link-tasks',
|
|
2834
|
+
duration_ms: durationMs,
|
|
2835
|
+
timestamp: new Date().toISOString(),
|
|
2836
|
+
},
|
|
2837
|
+
}, null, 2) + '\n');
|
|
2838
|
+
}
|
|
2839
|
+
else {
|
|
2840
|
+
process.stderr.write(`[nexus] Error running contracts link-tasks: ${msg}\n`);
|
|
2841
|
+
}
|
|
2842
|
+
process.exitCode = 1;
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2845
|
+
const result = response.data;
|
|
2846
|
+
if (jsonOutput) {
|
|
2847
|
+
process.stdout.write(JSON.stringify({
|
|
2848
|
+
success: true,
|
|
2849
|
+
data: result,
|
|
2850
|
+
meta: {
|
|
2851
|
+
operation: 'nexus.contracts.link-tasks',
|
|
2852
|
+
duration_ms: durationMs,
|
|
2853
|
+
timestamp: new Date().toISOString(),
|
|
2854
|
+
},
|
|
2855
|
+
}, null, 2) + '\n');
|
|
2856
|
+
}
|
|
2857
|
+
else {
|
|
2858
|
+
process.stdout.write(`[nexus] contracts link-tasks:\n` +
|
|
2859
|
+
` Commits processed: ${result.commitsProcessed}\n` +
|
|
2860
|
+
` Tasks found: ${result.tasksFound}\n` +
|
|
2861
|
+
` Edges linked: ${result.linked}\n` +
|
|
2862
|
+
` Last commit: ${result.lastCommitHash ?? '—'}\n` +
|
|
2863
|
+
` (${durationMs}ms)\n`);
|
|
2864
|
+
}
|
|
2865
|
+
},
|
|
2866
|
+
});
|
|
2867
|
+
/** cleo nexus contracts — contract extraction and compatibility operations */
|
|
2868
|
+
const contractsCommand = defineCommand({
|
|
2869
|
+
meta: { name: 'contracts', description: 'Contract extraction and compatibility operations' },
|
|
2870
|
+
subCommands: {
|
|
2871
|
+
sync: contractsSyncCommand,
|
|
2872
|
+
show: contractsShowCommand,
|
|
2873
|
+
'link-tasks': contractsLinkTasksCommand,
|
|
2874
|
+
},
|
|
2875
|
+
});
|
|
2876
|
+
/** cleo nexus group — alias for contracts subcommand (spec parity: T1114) */
|
|
2877
|
+
const groupCommand = defineCommand({
|
|
2878
|
+
meta: {
|
|
2879
|
+
name: 'group',
|
|
2880
|
+
description: 'Contract extraction and compatibility operations (alias for contracts)',
|
|
2881
|
+
},
|
|
2882
|
+
subCommands: {
|
|
2883
|
+
sync: contractsSyncCommand,
|
|
2884
|
+
show: contractsShowCommand,
|
|
2885
|
+
'link-tasks': contractsLinkTasksCommand,
|
|
2886
|
+
},
|
|
2887
|
+
});
|
|
2888
|
+
/** cleo nexus wiki — community-grouped wiki index with optional LOOM LLM summaries */
|
|
2889
|
+
const wikiCommand = defineCommand({
|
|
2890
|
+
meta: {
|
|
2891
|
+
name: 'wiki',
|
|
2892
|
+
description: 'Generate community-grouped wiki index from nexus code graph',
|
|
2893
|
+
},
|
|
2894
|
+
args: {
|
|
2895
|
+
output: {
|
|
2896
|
+
type: 'string',
|
|
2897
|
+
description: 'Output directory for wiki files (default: .cleo/wiki)',
|
|
2898
|
+
alias: 'o',
|
|
2899
|
+
},
|
|
2900
|
+
community: {
|
|
2901
|
+
type: 'string',
|
|
2902
|
+
description: 'Filter generation to a single community ID (e.g. "community:3")',
|
|
2903
|
+
alias: 'c',
|
|
2904
|
+
},
|
|
2905
|
+
incremental: {
|
|
2906
|
+
type: 'boolean',
|
|
2907
|
+
description: 'Only regenerate communities whose symbols changed since last wiki run (uses .cleo/wiki-state.json)',
|
|
2908
|
+
},
|
|
2909
|
+
json: {
|
|
2910
|
+
type: 'boolean',
|
|
2911
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
2912
|
+
},
|
|
2913
|
+
},
|
|
2914
|
+
async run({ args }) {
|
|
2915
|
+
const startTime = Date.now();
|
|
2916
|
+
const jsonOutput = !!args.json;
|
|
2917
|
+
const outputDir = args.output ?? path.join(process.cwd(), '.cleo', 'wiki');
|
|
2918
|
+
const communityFilter = args.community ?? undefined;
|
|
2919
|
+
const isIncremental = !!args.incremental;
|
|
2920
|
+
// SSoT-EXEMPT:loom-provider — LLM backend resolution for wiki generation requires
|
|
2921
|
+
// CLI-side async provider wiring that cannot be passed through the dispatch layer.
|
|
2922
|
+
// The dispatch 'wiki' op always uses loomProvider=null (scaffold mode). CLI-side
|
|
2923
|
+
// wiring enables real LLM narratives when a backend is available.
|
|
2924
|
+
// Resolve LOOM provider via the existing LLM backend resolver (warm tier).
|
|
2925
|
+
// Falls back gracefully — null means scaffold mode.
|
|
2926
|
+
// The 'ai' package lives in @cleocode/core's deps; we load it transitively.
|
|
2927
|
+
let loomProvider = null;
|
|
2928
|
+
try {
|
|
2929
|
+
const { resolveLlmBackend } = await import('@cleocode/core/memory/llm-backend-resolver.js');
|
|
2930
|
+
const backend = await resolveLlmBackend('warm');
|
|
2931
|
+
if (backend !== null && backend.name !== 'transformers') {
|
|
2932
|
+
// Wire as a simple text-completion function using the 'ai' package
|
|
2933
|
+
// loaded via @cleocode/core's node_modules (avoids duplicate dep in cleo).
|
|
2934
|
+
loomProvider = async (prompt) => {
|
|
2935
|
+
// Dynamic import at call time to avoid top-level resolution in cleo
|
|
2936
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2937
|
+
const aiMod = await import('ai');
|
|
2938
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
2939
|
+
const generateTextFn = aiMod.generateText;
|
|
2940
|
+
const { text } = await generateTextFn({
|
|
2941
|
+
model: backend.model,
|
|
2942
|
+
prompt,
|
|
2943
|
+
maxTokens: 256,
|
|
2944
|
+
});
|
|
2945
|
+
return text;
|
|
2946
|
+
};
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
catch {
|
|
2950
|
+
// LOOM unavailable — scaffold mode (logged inside generateNexusWikiIndex)
|
|
2951
|
+
loomProvider = null;
|
|
2952
|
+
}
|
|
2953
|
+
try {
|
|
2954
|
+
// SSoT-EXEMPT:loom-provider — must call generateNexusWikiIndex directly to pass
|
|
2955
|
+
// loomProvider. The dispatch 'wiki' op does not accept a loomProvider param.
|
|
2956
|
+
const { generateNexusWikiIndex } = await import('@cleocode/core/nexus/wiki-index.js');
|
|
2957
|
+
const result = await generateNexusWikiIndex(outputDir, process.cwd(), {
|
|
2958
|
+
communityFilter,
|
|
2959
|
+
incremental: isIncremental,
|
|
2960
|
+
loomProvider,
|
|
2961
|
+
projectRoot: process.cwd(),
|
|
2962
|
+
});
|
|
2963
|
+
const durationMs = Date.now() - startTime;
|
|
2964
|
+
if (jsonOutput) {
|
|
2965
|
+
process.stdout.write(JSON.stringify({
|
|
2966
|
+
success: result.success,
|
|
2967
|
+
data: result,
|
|
2968
|
+
meta: {
|
|
2969
|
+
operation: 'nexus.wiki',
|
|
2970
|
+
duration_ms: durationMs,
|
|
2971
|
+
timestamp: new Date().toISOString(),
|
|
2972
|
+
},
|
|
2973
|
+
}, null, 2) + '\n');
|
|
2974
|
+
}
|
|
2975
|
+
else {
|
|
2976
|
+
if (result.success) {
|
|
2977
|
+
const skippedNote = result.skippedCommunities && result.skippedCommunities.length > 0
|
|
2978
|
+
? `\n Skipped: ${result.skippedCommunities.length} unchanged communities`
|
|
2979
|
+
: '';
|
|
2980
|
+
const loomNote = result.loomEnabled ? ' (LOOM narratives enabled)' : ' (scaffold mode)';
|
|
2981
|
+
process.stdout.write(`[nexus] wiki generated${loomNote}:\n` +
|
|
2982
|
+
` Communities: ${result.communityCount}\n` +
|
|
2983
|
+
` Files: ${result.fileCount}\n` +
|
|
2984
|
+
` Output: ${outputDir}` +
|
|
2985
|
+
skippedNote +
|
|
2986
|
+
`\n (${durationMs}ms)\n`);
|
|
2987
|
+
}
|
|
2988
|
+
else {
|
|
2989
|
+
process.stderr.write(`[nexus] wiki generation failed: ${result.error}\n`);
|
|
2990
|
+
process.exitCode = 1;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
catch (err) {
|
|
2995
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
2996
|
+
if (jsonOutput) {
|
|
2997
|
+
process.stdout.write(JSON.stringify({
|
|
2998
|
+
success: false,
|
|
2999
|
+
error: { code: 'E_WIKI_GENERATION_FAILED', message: msg },
|
|
3000
|
+
meta: {
|
|
3001
|
+
operation: 'nexus.wiki',
|
|
3002
|
+
duration_ms: Date.now() - startTime,
|
|
3003
|
+
timestamp: new Date().toISOString(),
|
|
3004
|
+
},
|
|
3005
|
+
}, null, 2) + '\n');
|
|
3006
|
+
}
|
|
3007
|
+
else {
|
|
3008
|
+
process.stderr.write(`[nexus] Error generating wiki: ${msg}\n`);
|
|
3009
|
+
}
|
|
3010
|
+
process.exitCode = 1;
|
|
3011
|
+
}
|
|
3012
|
+
},
|
|
3013
|
+
});
|
|
3014
|
+
// ---------------------------------------------------------------------------
|
|
3015
|
+
// T1108 — Plasticity Query Commands (hot-paths, hot-nodes, cold-symbols)
|
|
3016
|
+
// ---------------------------------------------------------------------------
|
|
3017
|
+
/**
|
|
3018
|
+
* cleo nexus hot-paths — List highest-weight relation edges (Hebbian plasticity).
|
|
3019
|
+
*
|
|
3020
|
+
* Reads nexus_relations ORDER BY weight DESC, co_accessed_count DESC.
|
|
3021
|
+
* If no dream cycle has run yet (all weights 0), prints an informational
|
|
3022
|
+
* note and exits cleanly with an empty table.
|
|
3023
|
+
*
|
|
3024
|
+
* @task T1108
|
|
3025
|
+
*/
|
|
3026
|
+
const hotPathsCommand = defineCommand({
|
|
3027
|
+
meta: {
|
|
3028
|
+
name: 'hot-paths',
|
|
3029
|
+
description: 'List highest-weight relation edges by Hebbian plasticity weight',
|
|
3030
|
+
},
|
|
3031
|
+
args: {
|
|
3032
|
+
limit: {
|
|
3033
|
+
type: 'string',
|
|
3034
|
+
description: 'Maximum number of edges to return (default: 20)',
|
|
3035
|
+
default: '20',
|
|
3036
|
+
},
|
|
3037
|
+
json: {
|
|
3038
|
+
type: 'boolean',
|
|
3039
|
+
description: 'Output raw JSON',
|
|
3040
|
+
default: false,
|
|
3041
|
+
},
|
|
3042
|
+
},
|
|
3043
|
+
async run({ args }) {
|
|
3044
|
+
const limit = Number.parseInt(args.limit, 10) || 20;
|
|
3045
|
+
const jsonOutput = args.json;
|
|
3046
|
+
const startTime = Date.now();
|
|
3047
|
+
const response = await dispatchRaw('query', 'nexus', 'hot-paths', { limit });
|
|
3048
|
+
const durationMs = Date.now() - startTime;
|
|
3049
|
+
if (!response.success) {
|
|
3050
|
+
process.stderr.write(`[nexus hot-paths] Error: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
3051
|
+
process.exitCode = 1;
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
const result = response.data;
|
|
3055
|
+
if (jsonOutput) {
|
|
3056
|
+
process.stdout.write(JSON.stringify({
|
|
3057
|
+
success: true,
|
|
3058
|
+
data: result,
|
|
3059
|
+
meta: {
|
|
3060
|
+
operation: 'nexus.hot-paths',
|
|
3061
|
+
duration_ms: durationMs,
|
|
3062
|
+
timestamp: new Date().toISOString(),
|
|
3063
|
+
},
|
|
3064
|
+
}, null, 2) + '\n');
|
|
3065
|
+
return;
|
|
3066
|
+
}
|
|
3067
|
+
if (result.note) {
|
|
3068
|
+
process.stdout.write(`[nexus] Note: ${result.note}\n`);
|
|
3069
|
+
}
|
|
3070
|
+
if (result.paths.length === 0) {
|
|
3071
|
+
process.stdout.write('[nexus] No hot paths found.\n');
|
|
3072
|
+
return;
|
|
3073
|
+
}
|
|
3074
|
+
process.stdout.write('| Source | Target | Edge Type | Weight | Co-Access |\n| --- | --- | --- | --- | --- |\n');
|
|
3075
|
+
for (const p of result.paths) {
|
|
3076
|
+
process.stdout.write(`| ${p.sourceId} | ${p.targetId} | ${p.type} | ${p.weight.toFixed(4)} | ${p.coAccessedCount} |\n`);
|
|
3077
|
+
}
|
|
3078
|
+
process.stdout.write(`\n${result.count} edge(s) shown.\n`);
|
|
3079
|
+
},
|
|
3080
|
+
});
|
|
3081
|
+
/**
|
|
3082
|
+
* cleo nexus hot-nodes — List nodes with the highest aggregate Hebbian weight.
|
|
3083
|
+
*
|
|
3084
|
+
* Aggregates SUM(weight) per source node in nexus_relations, then joins
|
|
3085
|
+
* nexus_nodes for label/kind/file. If no dream cycle has run yet the table
|
|
3086
|
+
* is empty and an informational note is printed.
|
|
3087
|
+
*
|
|
3088
|
+
* @task T1108
|
|
3089
|
+
*/
|
|
3090
|
+
const hotNodesCommand = defineCommand({
|
|
3091
|
+
meta: {
|
|
3092
|
+
name: 'hot-nodes',
|
|
3093
|
+
description: 'List symbols with highest aggregate Hebbian weight',
|
|
3094
|
+
},
|
|
3095
|
+
args: {
|
|
3096
|
+
limit: {
|
|
3097
|
+
type: 'string',
|
|
3098
|
+
description: 'Maximum number of nodes to return (default: 20)',
|
|
3099
|
+
default: '20',
|
|
3100
|
+
},
|
|
3101
|
+
json: {
|
|
3102
|
+
type: 'boolean',
|
|
3103
|
+
description: 'Output raw JSON',
|
|
3104
|
+
default: false,
|
|
3105
|
+
},
|
|
3106
|
+
},
|
|
3107
|
+
async run({ args }) {
|
|
3108
|
+
const limit = Number.parseInt(args.limit, 10) || 20;
|
|
3109
|
+
const jsonOutput = args.json;
|
|
3110
|
+
const startTime = Date.now();
|
|
3111
|
+
const response = await dispatchRaw('query', 'nexus', 'hot-nodes', { limit });
|
|
3112
|
+
const durationMs = Date.now() - startTime;
|
|
3113
|
+
if (!response.success) {
|
|
3114
|
+
process.stderr.write(`[nexus hot-nodes] Error: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
3115
|
+
process.exitCode = 1;
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
const result = response.data;
|
|
3119
|
+
if (jsonOutput) {
|
|
3120
|
+
process.stdout.write(JSON.stringify({
|
|
3121
|
+
success: true,
|
|
3122
|
+
data: result,
|
|
3123
|
+
meta: {
|
|
3124
|
+
operation: 'nexus.hot-nodes',
|
|
3125
|
+
duration_ms: durationMs,
|
|
3126
|
+
timestamp: new Date().toISOString(),
|
|
3127
|
+
},
|
|
3128
|
+
}, null, 2) + '\n');
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
if (result.note) {
|
|
3132
|
+
process.stdout.write(`[nexus] Note: ${result.note}\n`);
|
|
3133
|
+
}
|
|
3134
|
+
if (result.nodes.length === 0) {
|
|
3135
|
+
process.stdout.write('[nexus] No hot nodes found.\n');
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
process.stdout.write('| Symbol | Total Weight | File | Kind |\n| --- | --- | --- | --- |\n');
|
|
3139
|
+
for (const n of result.nodes) {
|
|
3140
|
+
const file = n.filePath ?? '(unknown)';
|
|
3141
|
+
process.stdout.write(`| ${n.label} | ${n.totalWeight.toFixed(4)} | ${file} | ${n.kind} |\n`);
|
|
3142
|
+
}
|
|
3143
|
+
process.stdout.write(`\n${result.count} node(s) shown.\n`);
|
|
3144
|
+
},
|
|
3145
|
+
});
|
|
3146
|
+
/**
|
|
3147
|
+
* cleo nexus cold-symbols — List symbols that have gone cold.
|
|
3148
|
+
*
|
|
3149
|
+
* Returns symbols whose most-recent access (max last_accessed_at across
|
|
3150
|
+
* incident edges) is older than `--days` ago AND max weight < 0.1.
|
|
3151
|
+
* If last_accessed_at is NULL for all incident edges (no dream cycle run)
|
|
3152
|
+
* those symbols are included as infinitely cold.
|
|
3153
|
+
*
|
|
3154
|
+
* @task T1108
|
|
3155
|
+
*/
|
|
3156
|
+
const coldSymbolsCommand = defineCommand({
|
|
3157
|
+
meta: {
|
|
3158
|
+
name: 'cold-symbols',
|
|
3159
|
+
description: 'List cold symbols (stale access + low weight) for pruning candidates',
|
|
3160
|
+
},
|
|
3161
|
+
args: {
|
|
3162
|
+
days: {
|
|
3163
|
+
type: 'string',
|
|
3164
|
+
description: 'Age threshold in days (default: 30)',
|
|
3165
|
+
default: '30',
|
|
3166
|
+
},
|
|
3167
|
+
json: {
|
|
3168
|
+
type: 'boolean',
|
|
3169
|
+
description: 'Output raw JSON',
|
|
3170
|
+
default: false,
|
|
3171
|
+
},
|
|
3172
|
+
},
|
|
3173
|
+
async run({ args }) {
|
|
3174
|
+
const thresholdDays = Number.parseInt(args.days, 10) || 30;
|
|
3175
|
+
const jsonOutput = args.json;
|
|
3176
|
+
const startTime = Date.now();
|
|
3177
|
+
const response = await dispatchRaw('query', 'nexus', 'cold-symbols', { days: thresholdDays });
|
|
3178
|
+
const durationMs = Date.now() - startTime;
|
|
3179
|
+
if (!response.success) {
|
|
3180
|
+
process.stderr.write(`[nexus cold-symbols] Error: ${response.error?.message ?? 'Unknown error'}\n`);
|
|
3181
|
+
process.exitCode = 1;
|
|
3182
|
+
return;
|
|
3183
|
+
}
|
|
3184
|
+
const result = response.data;
|
|
3185
|
+
if (jsonOutput) {
|
|
3186
|
+
process.stdout.write(JSON.stringify({
|
|
3187
|
+
success: true,
|
|
3188
|
+
data: result,
|
|
3189
|
+
meta: {
|
|
3190
|
+
operation: 'nexus.cold-symbols',
|
|
3191
|
+
duration_ms: durationMs,
|
|
3192
|
+
timestamp: new Date().toISOString(),
|
|
3193
|
+
},
|
|
3194
|
+
}, null, 2) + '\n');
|
|
3195
|
+
return;
|
|
3196
|
+
}
|
|
3197
|
+
if (result.note) {
|
|
3198
|
+
process.stdout.write(`[nexus] Note: ${result.note}\n`);
|
|
3199
|
+
}
|
|
3200
|
+
if (result.symbols.length === 0) {
|
|
3201
|
+
process.stdout.write(`[nexus] No cold symbols found (threshold: ${thresholdDays} days, weight < 0.1).\n`);
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
process.stdout.write('| Symbol | Last Accessed | Weight | File |\n| --- | --- | --- | --- |\n');
|
|
3205
|
+
for (const s of result.symbols) {
|
|
3206
|
+
const lastAccessed = s.lastAccessed ?? '(never)';
|
|
3207
|
+
const file = s.filePath ?? '(unknown)';
|
|
3208
|
+
process.stdout.write(`| ${s.label} | ${lastAccessed} | ${s.maxWeight.toFixed(4)} | ${file} |\n`);
|
|
3209
|
+
}
|
|
3210
|
+
process.stdout.write(`\n${result.count} cold symbol(s) found (threshold: ${thresholdDays} days).\n`);
|
|
3211
|
+
},
|
|
3212
|
+
});
|
|
3213
|
+
/**
|
|
3214
|
+
* cleo nexus top-entries — List top-weighted symbols from nexus_relations.
|
|
3215
|
+
*
|
|
3216
|
+
* Returns the highest-weighted source nodes from the Hebbian plasticity
|
|
3217
|
+
* relation graph (T998). Each entry is aggregated SUM(weight) per source_id
|
|
3218
|
+
* joined with nexus_nodes for label / kind / file-path. Supports optional
|
|
3219
|
+
* `--kind` filter (e.g. function, method, class) and `--limit` (default 20).
|
|
3220
|
+
*
|
|
3221
|
+
* Routes through the dispatch layer so all transports (CLI, TUI, agents) see
|
|
3222
|
+
* the same LAFS envelope shape (see `handleTopEntries` in
|
|
3223
|
+
* `packages/cleo/src/dispatch/domains/nexus.ts`).
|
|
3224
|
+
*
|
|
3225
|
+
* @task T1013
|
|
3226
|
+
* @epic T1006
|
|
3227
|
+
*/
|
|
3228
|
+
// ── T1386: sigil sync + list ─────────────────────────────────────────
|
|
3229
|
+
/** cleo nexus sigil sync — populate sigils table from canonical CANT agents */
|
|
3230
|
+
const sigilSyncCommand = defineCommand({
|
|
3231
|
+
meta: {
|
|
3232
|
+
name: 'sync',
|
|
3233
|
+
description: 'Populate the nexus.db sigils table with one row per canonical CANT agent (cleo-subagent + 5 seed roles + 2 meta agents). Idempotent.',
|
|
3234
|
+
},
|
|
3235
|
+
args: {
|
|
3236
|
+
json: {
|
|
3237
|
+
type: 'boolean',
|
|
3238
|
+
description: 'Output as JSON (LAFS envelope format)',
|
|
3239
|
+
},
|
|
3240
|
+
},
|
|
3241
|
+
async run() {
|
|
3242
|
+
await dispatchFromCli('mutate', 'nexus', 'sigil.sync', {}, { command: 'nexus' });
|
|
3243
|
+
},
|
|
3244
|
+
});
|
|
3245
|
+
/** cleo nexus sigil list — list every sigil currently stored in nexus.db */
|
|
3246
|
+
const sigilListCommand = defineCommand({
|
|
3247
|
+
meta: {
|
|
3248
|
+
name: 'list',
|
|
3249
|
+
description: 'List every sigil currently stored in nexus.db, optionally filtered by role.',
|
|
3250
|
+
},
|
|
3251
|
+
args: {
|
|
3252
|
+
role: {
|
|
3253
|
+
type: 'string',
|
|
3254
|
+
description: 'Filter by role (e.g. "orchestrator", "lead", "worker", "specialist", "subagent")',
|
|
3255
|
+
},
|
|
3256
|
+
},
|
|
3257
|
+
async run({ args }) {
|
|
3258
|
+
await dispatchFromCli('query', 'nexus', 'sigil.list', { role: args.role }, { command: 'nexus' });
|
|
3259
|
+
},
|
|
3260
|
+
});
|
|
3261
|
+
/** cleo nexus sigil — group alias for `sync` and `list`. */
|
|
3262
|
+
const sigilCommand = defineCommand({
|
|
3263
|
+
meta: {
|
|
3264
|
+
name: 'sigil',
|
|
3265
|
+
description: 'Sigil (peer-card) operations — sync from canonical CANT agents, list current rows',
|
|
3266
|
+
},
|
|
3267
|
+
subCommands: {
|
|
3268
|
+
sync: sigilSyncCommand,
|
|
3269
|
+
list: sigilListCommand,
|
|
3270
|
+
},
|
|
3271
|
+
});
|
|
3272
|
+
const topEntriesCommand = defineCommand({
|
|
3273
|
+
meta: {
|
|
3274
|
+
name: 'top-entries',
|
|
3275
|
+
description: 'List top-weighted symbols from nexus_relations by weight DESC',
|
|
3276
|
+
},
|
|
3277
|
+
args: {
|
|
3278
|
+
limit: {
|
|
3279
|
+
type: 'string',
|
|
3280
|
+
description: 'Maximum number of entries to return (default: 20)',
|
|
3281
|
+
default: '20',
|
|
3282
|
+
},
|
|
3283
|
+
kind: {
|
|
3284
|
+
type: 'string',
|
|
3285
|
+
description: 'Filter by nexus_nodes.kind (e.g. function, method, class, interface, type_alias)',
|
|
3286
|
+
},
|
|
3287
|
+
json: {
|
|
3288
|
+
type: 'boolean',
|
|
3289
|
+
description: 'Output result as JSON (LAFS envelope format)',
|
|
3290
|
+
},
|
|
3291
|
+
},
|
|
3292
|
+
async run({ args }) {
|
|
3293
|
+
const limit = Number.parseInt(args.limit, 10) || 20;
|
|
3294
|
+
const kind = args.kind ?? undefined;
|
|
3295
|
+
const jsonOutput = !!args.json;
|
|
3296
|
+
const params = { limit };
|
|
3297
|
+
if (kind !== undefined && kind.length > 0)
|
|
3298
|
+
params.kind = kind;
|
|
3299
|
+
await dispatchFromCli('query', 'nexus', 'top-entries', params, {
|
|
3300
|
+
command: 'nexus',
|
|
3301
|
+
operation: 'nexus.top-entries',
|
|
3302
|
+
...(jsonOutput ? { json: true } : {}),
|
|
3303
|
+
});
|
|
3304
|
+
},
|
|
3305
|
+
});
|
|
3306
|
+
export const nexusCommand = defineCommand({
|
|
3307
|
+
meta: { name: 'nexus', description: 'Cross-project NEXUS operations' },
|
|
3308
|
+
subCommands: {
|
|
3309
|
+
init: initCommand,
|
|
3310
|
+
register: registerCommand,
|
|
3311
|
+
unregister: unregisterCommand,
|
|
3312
|
+
list: listCommand,
|
|
3313
|
+
status: statusCommand,
|
|
3314
|
+
show: showCommand,
|
|
3315
|
+
resolve: resolveCommand,
|
|
3316
|
+
discover: discoverCommand,
|
|
3317
|
+
search: searchCommand,
|
|
3318
|
+
augment: augmentCommand,
|
|
3319
|
+
setup: setupCommand,
|
|
3320
|
+
deps: depsCommand,
|
|
3321
|
+
'critical-path': criticalPathCommand,
|
|
3322
|
+
blocking: blockingCommand,
|
|
3323
|
+
orphans: orphansCommand,
|
|
3324
|
+
sync: syncCommand,
|
|
3325
|
+
reconcile: reconcileCommand,
|
|
3326
|
+
graph: graphCommand,
|
|
3327
|
+
'share-status': shareStatusCommand,
|
|
3328
|
+
'transfer-preview': transferPreviewCommand,
|
|
3329
|
+
transfer: transferCommand,
|
|
3330
|
+
permission: permissionCommand,
|
|
3331
|
+
share: shareCommand,
|
|
3332
|
+
clusters: clustersCommand,
|
|
3333
|
+
flows: flowsCommand,
|
|
3334
|
+
context: contextCommand,
|
|
3335
|
+
impact: impactCommand,
|
|
3336
|
+
analyze: analyzeCommand,
|
|
3337
|
+
query: queryCommand,
|
|
3338
|
+
projects: projectsCommand,
|
|
3339
|
+
'refresh-bridge': refreshBridgeCommand,
|
|
3340
|
+
export: exportCommand,
|
|
3341
|
+
diff: diffCommand,
|
|
3342
|
+
'route-map': routeMapCommand,
|
|
3343
|
+
'shape-check': shapeCheckCommand,
|
|
3344
|
+
'full-context': fullContextCommand,
|
|
3345
|
+
'task-footprint': taskFootprintCommand,
|
|
3346
|
+
'brain-anchors': brainAnchorsCommand,
|
|
3347
|
+
why: whyCommand,
|
|
3348
|
+
'impact-full': impactFullCommand,
|
|
3349
|
+
// T1071 — conduit scan
|
|
3350
|
+
'conduit-scan': conduitScanCommand,
|
|
3351
|
+
// T1067 — task symbols
|
|
3352
|
+
'task-symbols': taskSymbolsCommand,
|
|
3353
|
+
// T1058 — code symbol search
|
|
3354
|
+
'search-code': searchCodeCommand,
|
|
3355
|
+
// T1065 — contract registry
|
|
3356
|
+
contracts: contractsCommand,
|
|
3357
|
+
// T1114 — group alias for contracts
|
|
3358
|
+
group: groupCommand,
|
|
3359
|
+
// T1060 — wiki index
|
|
3360
|
+
wiki: wikiCommand,
|
|
3361
|
+
// T1108 — plasticity queries
|
|
3362
|
+
'hot-paths': hotPathsCommand,
|
|
3363
|
+
'hot-nodes': hotNodesCommand,
|
|
3364
|
+
'cold-symbols': coldSymbolsCommand,
|
|
3365
|
+
// T1013 / T1006 — top-weighted symbols by nexus_relations.weight
|
|
3366
|
+
'top-entries': topEntriesCommand,
|
|
3367
|
+
// T1386 — sigil sync + list (canonical CANT agent peer cards)
|
|
3368
|
+
sigil: sigilCommand,
|
|
3369
|
+
},
|
|
3370
|
+
async run({ cmd, rawArgs }) {
|
|
3371
|
+
const firstArg = rawArgs?.find((a) => !a.startsWith('-'));
|
|
3372
|
+
if (firstArg && cmd.subCommands && firstArg in cmd.subCommands)
|
|
3373
|
+
return;
|
|
3374
|
+
await showUsage(cmd);
|
|
3375
|
+
},
|
|
3376
|
+
});
|
|
3377
|
+
//# sourceMappingURL=nexus.js.map
|