@synap-core/cli 1.8.0 → 1.11.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/commands/agent-chat.d.ts +47 -0
- package/dist/commands/agent-chat.js +250 -0
- package/dist/commands/agent-chat.js.map +1 -0
- package/dist/commands/agent-run.js +3 -4
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/agents.js +85 -46
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/automation.js +2 -1
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/bridge-setup.d.ts +66 -0
- package/dist/commands/bridge-setup.js +1112 -0
- package/dist/commands/bridge-setup.js.map +1 -0
- package/dist/commands/cap-connections.d.ts +28 -0
- package/dist/commands/cap-connections.js +224 -0
- package/dist/commands/cap-connections.js.map +1 -0
- package/dist/commands/capability.d.ts +89 -0
- package/dist/commands/capability.js +1594 -0
- package/dist/commands/capability.js.map +1 -0
- package/dist/commands/centrality.d.ts +20 -0
- package/dist/commands/centrality.js +95 -0
- package/dist/commands/centrality.js.map +1 -0
- package/dist/commands/connect.d.ts +2 -0
- package/dist/commands/connect.js +16 -35
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +6 -7
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +1 -0
- package/dist/commands/data-extra.js +41 -14
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +4 -4
- package/dist/commands/data.js +254 -187
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +20 -0
- package/dist/commands/diagnose.js +186 -0
- package/dist/commands/diagnose.js.map +1 -0
- package/dist/commands/digest.d.ts +17 -0
- package/dist/commands/digest.js +122 -0
- package/dist/commands/digest.js.map +1 -0
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.js +25 -8
- package/dist/commands/discover.js.map +1 -1
- package/dist/commands/doc.d.ts +14 -0
- package/dist/commands/doc.js +61 -4
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +21 -0
- package/dist/commands/doctor.js +189 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.js +5 -2
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/explain.d.ts +1 -1
- package/dist/commands/explain.js +18 -15
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/facet.d.ts +29 -0
- package/dist/commands/facet.js +113 -0
- package/dist/commands/facet.js.map +1 -0
- package/dist/commands/graph.js +7 -4
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +38 -0
- package/dist/commands/import.js +471 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/init.js +35 -16
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.js +3 -4
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/knowledge.d.ts +8 -0
- package/dist/commands/knowledge.js +308 -33
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/launch.d.ts +50 -0
- package/dist/commands/launch.js +790 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/lens.d.ts +45 -0
- package/dist/commands/lens.js +386 -0
- package/dist/commands/lens.js.map +1 -0
- package/dist/commands/market-authoring.d.ts +45 -0
- package/dist/commands/market-authoring.js +225 -0
- package/dist/commands/market-authoring.js.map +1 -0
- package/dist/commands/market.d.ts +224 -0
- package/dist/commands/market.js +1643 -0
- package/dist/commands/market.js.map +1 -0
- package/dist/commands/mcp.d.ts +64 -0
- package/dist/commands/mcp.js +265 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/observe.js +14 -11
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/open.d.ts +21 -4
- package/dist/commands/open.js +45 -4
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/pod.d.ts +100 -0
- package/dist/commands/pod.js +359 -0
- package/dist/commands/pod.js.map +1 -0
- package/dist/commands/pods.d.ts +15 -0
- package/dist/commands/pods.js +233 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +43 -3
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/purge.d.ts +23 -0
- package/dist/commands/purge.js +148 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +153 -0
- package/dist/commands/raycast.js.map +1 -0
- package/dist/commands/sessions.js +47 -22
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skill-manage.d.ts +21 -0
- package/dist/commands/skill-manage.js +195 -0
- package/dist/commands/skill-manage.js.map +1 -0
- package/dist/commands/skills-commands.js +2 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills.js +7 -4
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +3 -1
- package/dist/commands/status.js +166 -14
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.d.ts +24 -0
- package/dist/commands/statusline.js +450 -0
- package/dist/commands/statusline.js.map +1 -0
- package/dist/commands/subscribe.js +2 -2
- package/dist/commands/subscribe.js.map +1 -1
- package/dist/commands/template.d.ts +42 -0
- package/dist/commands/template.js +191 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/tools.d.ts +30 -0
- package/dist/commands/tools.js +315 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/upload.d.ts +30 -0
- package/dist/commands/upload.js +155 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/versions.d.ts +27 -0
- package/dist/commands/versions.js +277 -0
- package/dist/commands/versions.js.map +1 -0
- package/dist/commands/view.js +3 -2
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/whoami.d.ts +21 -0
- package/dist/commands/whoami.js +129 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/index.js +894 -60
- package/dist/index.js.map +1 -1
- package/dist/lib/approval-poll.d.ts +42 -0
- package/dist/lib/approval-poll.js +52 -0
- package/dist/lib/approval-poll.js.map +1 -0
- package/dist/lib/auth.d.ts +29 -6
- package/dist/lib/auth.js +105 -94
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/bundle-version.d.ts +11 -0
- package/dist/lib/bundle-version.js +33 -0
- package/dist/lib/bundle-version.js.map +1 -0
- package/dist/lib/capture-lane.d.ts +30 -12
- package/dist/lib/capture-lane.js +73 -14
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +123 -0
- package/dist/lib/capture-structure.js +57 -0
- package/dist/lib/capture-structure.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +177 -0
- package/dist/lib/cp-packages.js +389 -0
- package/dist/lib/cp-packages.js.map +1 -0
- package/dist/lib/describe-lens.d.ts +46 -0
- package/dist/lib/describe-lens.js +33 -0
- package/dist/lib/describe-lens.js.map +1 -0
- package/dist/lib/hub-client.d.ts +91 -1
- package/dist/lib/hub-client.js +565 -22
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/id.d.ts +23 -0
- package/dist/lib/id.js +35 -0
- package/dist/lib/id.js.map +1 -0
- package/dist/lib/installed.d.ts +51 -0
- package/dist/lib/installed.js +70 -0
- package/dist/lib/installed.js.map +1 -0
- package/dist/lib/next-steps.d.ts +61 -0
- package/dist/lib/next-steps.js +146 -0
- package/dist/lib/next-steps.js.map +1 -0
- package/dist/lib/pod.d.ts +144 -22
- package/dist/lib/pod.js +302 -64
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/project-ref.d.ts +95 -0
- package/dist/lib/project-ref.js +144 -0
- package/dist/lib/project-ref.js.map +1 -0
- package/dist/lib/project.d.ts +35 -0
- package/dist/lib/project.js +39 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/session-lens.d.ts +33 -0
- package/dist/lib/session-lens.js +76 -0
- package/dist/lib/session-lens.js.map +1 -0
- package/dist/lib/skill-import.d.ts +40 -0
- package/dist/lib/skill-import.js +203 -0
- package/dist/lib/skill-import.js.map +1 -0
- package/dist/lib/skills-installer.d.ts +17 -6
- package/dist/lib/skills-installer.js +133 -19
- package/dist/lib/skills-installer.js.map +1 -1
- package/dist/lib/suite.d.ts +28 -0
- package/dist/lib/suite.js +29 -0
- package/dist/lib/suite.js.map +1 -0
- package/dist/lib/superwhisper-import.d.ts +40 -0
- package/dist/lib/superwhisper-import.js +389 -0
- package/dist/lib/superwhisper-import.js.map +1 -0
- package/dist/lib/targets.d.ts +49 -1
- package/dist/lib/targets.js +420 -288
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +74 -0
- package/dist/lib/template-file.js +140 -0
- package/dist/lib/template-file.js.map +1 -0
- package/dist/lib/unwrapList.d.ts +1 -0
- package/dist/lib/unwrapList.js +20 -0
- package/dist/lib/unwrapList.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +10 -2
- package/dist/utils/logger.js.map +1 -1
- package/node_modules/@synap/hub-rest-client/dist/index.cjs +414 -34
- package/node_modules/@synap/hub-rest-client/dist/index.d.cts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.d.ts +762 -22
- package/node_modules/@synap/hub-rest-client/dist/index.js +414 -34
- package/node_modules/@synap/hub-rest-client/package.json +1 -1
- package/node_modules/@synap/hub-rest-client/src/client.ts +525 -37
- package/node_modules/@synap/hub-rest-client/src/index.ts +42 -0
- package/node_modules/@synap/hub-rest-client/src/setup.ts +57 -1
- package/node_modules/@synap/hub-rest-client/src/types.ts +697 -37
- package/package.json +11 -5
- package/skills/agent-os/SKILL.md +218 -0
- package/skills/manifest.json +5 -0
- package/skills/onboard/SKILL.md +193 -0
- package/skills/synap/SKILL.md +1284 -58
- package/skills/synap/_order.txt +37 -0
- package/skills/synap/_skill.yaml +24 -0
- package/skills/synap/authentication.md +10 -0
- package/skills/synap/automations.md +264 -0
- package/skills/synap/capabilities.md +107 -0
- package/skills/synap/capture.md +50 -142
- package/skills/synap/cli-operations.md +107 -0
- package/skills/synap/common-mistakes.md +13 -0
- package/skills/synap/content-os.md +83 -0
- package/skills/synap/creative-loop.md +43 -0
- package/skills/synap/crm.md +117 -0
- package/skills/synap/diagnostics.md +35 -0
- package/skills/synap/digesting-a-channel.md +63 -0
- package/skills/synap/document-embeds.md +123 -0
- package/skills/synap/escalation-ladder.md +71 -0
- package/skills/synap/focus-sessions.md +47 -0
- package/skills/synap/governance-rules.md +64 -0
- package/skills/synap/governance.md +6 -6
- package/skills/synap/graph-gardening.md +21 -0
- package/skills/synap/inline-patterns.md +38 -0
- package/skills/synap/lenses.md +38 -0
- package/skills/synap/linking-principle.md +39 -0
- package/skills/synap/linking.md +1 -0
- package/skills/synap/mental-model.md +45 -0
- package/skills/synap/more.md +7 -0
- package/skills/synap/multi-entity-capture.md +12 -0
- package/skills/synap/next-action.md +37 -0
- package/skills/synap/north-star.md +17 -0
- package/skills/synap/operating-mode-rules.md +45 -0
- package/skills/synap/operating-mode.md +9 -0
- package/skills/synap/quick-reference.md +67 -0
- package/skills/synap/reading.md +43 -0
- package/skills/synap/recap.md +21 -0
- package/skills/synap/reflexes.md +46 -0
- package/skills/synap/response-style.md +21 -0
- package/skills/synap/scope.md +13 -0
- package/skills/synap/showing.md +17 -0
- package/skills/synap/user-model.md +25 -0
- package/skills/synap/viewframe-cells.md +290 -0
- package/skills/synap/work-flow.md +113 -0
- package/skills/synap/worked-examples.md +74 -0
- package/skills/synap/workspace-design.md +45 -0
- package/skills/synap/workspace-edges.md +49 -0
- package/skills/synap/writes.md +213 -0
- package/skills/synap-app/SKILL.md +319 -0
- package/skills/synap-app/_order.txt +5 -0
- package/skills/synap-app/_skill.yaml +20 -0
- package/skills/synap-app/creating-the-base-app.md +64 -0
- package/skills/synap-app/governance.md +42 -0
- package/skills/synap-app/install-commands.md +55 -0
- package/skills/synap-app/overview.md +50 -0
- package/skills/synap-app/using-the-sdk.md +73 -0
- package/skills/synap-market/SKILL.md +335 -0
- package/skills/synap-market/_order.txt +5 -0
- package/skills/synap-market/_skill.yaml +24 -0
- package/skills/synap-market/author-and-publish.md +75 -0
- package/skills/synap-market/discover-and-fetch.md +59 -0
- package/skills/synap-market/governance-and-catalog.md +56 -0
- package/skills/synap-market/install.md +55 -0
- package/skills/synap-market/overview.md +51 -0
- package/skills/synap-schema/SKILL.md +97 -6
- package/skills/synap-schema/_order.txt +13 -0
- package/skills/synap-schema/_skill.yaml +22 -0
- package/skills/synap-schema/before-you-touch.md +14 -0
- package/skills/synap-schema/common-mistakes.md +9 -0
- package/skills/synap-schema/creating-profiles.md +17 -0
- package/skills/synap-schema/discover-profiles.md +24 -0
- package/skills/synap-schema/entity-scope.md +8 -0
- package/skills/synap-schema/extend-vs-create.md +31 -0
- package/skills/synap-schema/more.md +6 -0
- package/skills/synap-schema/overlay-properties.md +22 -0
- package/skills/synap-schema/profiles.md +3 -0
- package/skills/synap-schema/property-defs.md +29 -0
- package/skills/synap-schema/read-before-write.md +50 -0
- package/skills/synap-schema/relations.md +18 -0
- package/skills/synap-schema/worked-example.md +30 -0
- package/skills/synap-ui/SKILL.md +26 -2
- package/skills/synap-ui/_order.txt +13 -0
- package/skills/synap-ui/_skill.yaml +23 -0
- package/skills/synap-ui/ai-companion.md +27 -0
- package/skills/synap-ui/arranging-bento.md +8 -0
- package/skills/synap-ui/before-you-build.md +20 -0
- package/skills/synap-ui/bento-layouts.md +35 -0
- package/skills/synap-ui/common-mistakes.md +10 -0
- package/skills/synap-ui/creating-views.md +26 -0
- package/skills/synap-ui/four-builds.md +24 -0
- package/skills/synap-ui/more.md +7 -0
- package/skills/synap-ui/proposing-vs-extending.md +11 -0
- package/skills/synap-ui/view-list.md +24 -0
- package/skills/synap-ui/views.md +3 -0
- package/skills/synap-ui/worked-example.md +18 -0
- package/skills/synap-ui/workspaces.md +47 -0
- package/templates/automations/bookmark-enrichment.automation.json +44 -0
- package/templates/automations/mail-feed.automation.json +86 -0
- package/templates/automations/url-bookmark-capture.automation.json +70 -0
- package/templates/skills/README.md +21 -0
- package/templates/skills/authoring-automations/SKILL.md +95 -0
- package/templates/skills/authoring-automations/reference/node-matrix.md +49 -0
- package/templates/skills/authoring-capabilities/SKILL.md +93 -0
- package/templates/skills/authoring-capabilities/reference/template-anatomy.md +70 -0
- package/templates/skills/authoring-playbooks/SKILL.md +102 -0
- package/templates/skills/authoring-playbooks/reference/stages-contract.md +35 -0
- package/templates/skills/authoring-playbooks/reference/worked-example.md +64 -0
- package/templates/skills/bookmark-enrichment/SKILL.md +40 -0
- package/templates/skills/coordinating-agents/SKILL.md +32 -0
- package/templates/skills/coordinating-branches/SKILL.md +27 -0
- package/templates/skills/mapping-the-server/SKILL.md +54 -0
- package/templates/skills/reading-client-progress/SKILL.md +65 -0
- package/templates/skills/routing-to-channels/SKILL.md +54 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
- package/templates/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
- package/templates/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
- package/templates/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
- package/templates/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
- package/templates/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
- package/templates/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
- package/templates/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
- package/dist/commands/connectors.d.ts +0 -31
- package/dist/commands/connectors.js +0 -276
- package/dist/commands/connectors.js.map +0 -1
- package/dist/commands/finish.d.ts +0 -25
- package/dist/commands/finish.js +0 -274
- package/dist/commands/finish.js.map +0 -1
- package/dist/commands/openclaw.d.ts +0 -40
- package/dist/commands/openclaw.js +0 -1148
- package/dist/commands/openclaw.js.map +0 -1
- package/dist/commands/security-audit.d.ts +0 -12
- package/dist/commands/security-audit.js +0 -100
- package/dist/commands/security-audit.js.map +0 -1
- package/dist/lib/hardening.d.ts +0 -18
- package/dist/lib/hardening.js +0 -214
- package/dist/lib/hardening.js.map +0 -1
package/dist/commands/data.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { log } from "../utils/logger.js";
|
|
3
|
-
import { resolveHubConfig, resolveUserId, hubGet, hubPost, hubPatch } from "../lib/hub-client.js";
|
|
4
|
-
import {
|
|
3
|
+
import { resolveHubConfig, resolveUserId, hubGet, hubPost, hubPatch, readActiveSessionId, renderHubError } from "../lib/hub-client.js";
|
|
4
|
+
import { unwrapList } from "../lib/unwrapList.js";
|
|
5
|
+
import { reportWrite } from "../lib/capture-lane.js";
|
|
6
|
+
import { renderNextSteps, FLOW } from "../lib/next-steps.js";
|
|
7
|
+
import { requireFullId } from "../lib/id.js";
|
|
5
8
|
export const parseLimit = (s, def) => s ? parseInt(s, 10) : def;
|
|
6
9
|
export function formatHit(hit) {
|
|
7
10
|
const doc = (hit.document ?? hit);
|
|
@@ -10,115 +13,120 @@ export function formatHit(hit) {
|
|
|
10
13
|
// `type` is the entity's profile (entities carry `type`; search hits carry
|
|
11
14
|
// `entityType`/`collection`). Include `doc.type` or the badge renders blank.
|
|
12
15
|
type: String(doc.entityType ?? doc.profileSlug ?? doc.type ?? hit.collection ?? ""),
|
|
13
|
-
id:
|
|
16
|
+
// Full id, never truncated: this is the handle callers feed straight back
|
|
17
|
+
// into `synap get entity <id>` — an 8-char prefix isn't a valid UUID and
|
|
18
|
+
// 500s on the pod (see `renderHubError`'s uuid-shape hint).
|
|
19
|
+
id: String(doc.id ?? hit.id ?? ""),
|
|
14
20
|
};
|
|
15
21
|
}
|
|
16
|
-
// ─── orient ───────────────────────────────────────────────────────────────────
|
|
17
22
|
export async function orient(opts) {
|
|
18
23
|
try {
|
|
19
24
|
const cfg = await resolveHubConfig(opts);
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const userId = String(me
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
// Newer pods return `entityCount` directly on GET /workspaces; for older
|
|
30
|
-
// pods fall back to counting a real page of entities (GET /entities
|
|
31
|
-
// returns a bare array — there is no `total` field on the wire).
|
|
32
|
-
const FALLBACK_PAGE = 100;
|
|
33
|
-
const wsDetails = await Promise.all(wsList.map(async (ws) => {
|
|
34
|
-
const wsId = String(ws.id ?? "");
|
|
35
|
-
const declaredCount = typeof ws.entityCount === "number" ? ws.entityCount : undefined;
|
|
36
|
-
const [profilesRes, entitiesRes] = await Promise.allSettled([
|
|
37
|
-
hubGet("/profiles", { userId, workspaceId: wsId }, cfg),
|
|
38
|
-
declaredCount === undefined
|
|
39
|
-
? hubGet("/entities", { userId, workspaceId: wsId, limit: FALLBACK_PAGE }, cfg)
|
|
40
|
-
: Promise.resolve(null),
|
|
41
|
-
]);
|
|
42
|
-
const profiles = profilesRes.status === "fulfilled"
|
|
43
|
-
? (profilesRes.value.profiles ?? profilesRes.value)
|
|
44
|
-
: [];
|
|
45
|
-
const profileList = Array.isArray(profiles) ? profiles : [];
|
|
46
|
-
let entityTotal = declaredCount ?? 0;
|
|
47
|
-
let countIsLowerBound = false;
|
|
48
|
-
if (declaredCount === undefined && entitiesRes.status === "fulfilled" && entitiesRes.value) {
|
|
49
|
-
const v = entitiesRes.value;
|
|
50
|
-
const arr = Array.isArray(v) ? v : (v.entities ?? []);
|
|
51
|
-
entityTotal = Array.isArray(arr) ? arr.length : 0;
|
|
52
|
-
countIsLowerBound = entityTotal === FALLBACK_PAGE;
|
|
53
|
-
}
|
|
54
|
-
return { ws, profileList, entityTotal, countIsLowerBound };
|
|
55
|
-
}));
|
|
25
|
+
// ONE canonical shape: the backend `discover()` service (via GET /orient)
|
|
26
|
+
// assembles the lens map — workspaces + projects + profile sample +
|
|
27
|
+
// disclosure (onboarding→goal, entity counts, per-ws profiles under full).
|
|
28
|
+
// The CLI only RENDERS it; `--details` maps to detail:'full'. No client-side
|
|
29
|
+
// assembly, no N+1 fanout — the server does the shaping.
|
|
30
|
+
const res = (await hubGet("/orient", opts.details ? { detail: "full" } : {}, cfg));
|
|
31
|
+
const userId = String(res.me?.userId ?? cfg.userId);
|
|
32
|
+
const projList = res.projects ?? [];
|
|
33
|
+
const wsList = res.workspaces ?? [];
|
|
56
34
|
if (opts.json) {
|
|
57
|
-
|
|
58
|
-
"synap graph --entity <id> --depth 2",
|
|
59
|
-
"synap events --entity <id>",
|
|
60
|
-
"synap subscribe --event entity.*",
|
|
61
|
-
"synap context",
|
|
62
|
-
"synap automation list",
|
|
63
|
-
"synap list views --type whiteboard",
|
|
64
|
-
"synap view create --type kanban --profile task",
|
|
65
|
-
"synap proposals list",
|
|
66
|
-
"synap explain",
|
|
67
|
-
];
|
|
68
|
-
console.log(JSON.stringify({ userId, podUrl: cfg.podUrl, workspaceId: cfg.workspaceId, workspaces: wsDetails, me, capabilities }, null, 2));
|
|
35
|
+
console.log(JSON.stringify({ ...res, podUrl: cfg.podUrl, workspaceId: cfg.workspaceId, nextSteps: FLOW.afterOrient() }, null, 2));
|
|
69
36
|
return;
|
|
70
37
|
}
|
|
38
|
+
// Render content rows with console.log (default terminal fg) rather than
|
|
39
|
+
// log.info — log.info wraps every line in chalk.blue, and that blue fg
|
|
40
|
+
// persists through inner bold/dim (they reset weight, not color), flattening
|
|
41
|
+
// the hierarchy. We keep only targeted accents: bold=name, dim=metadata,
|
|
42
|
+
// green ▶ = active.
|
|
71
43
|
log.heading("Pod Orientation");
|
|
72
|
-
log
|
|
73
|
-
log
|
|
74
|
-
|
|
75
|
-
|
|
44
|
+
console.log(` User : ${userId}`);
|
|
45
|
+
console.log(` Pod URL : ${cfg.podUrl}`);
|
|
46
|
+
// The per-Claude-session lens (project + workspace + session) — "where am I".
|
|
47
|
+
// Full ids so they can be pasted into 'synap project use' / 'synap use'.
|
|
48
|
+
const { getClaudeSessionId, resolveActiveLens } = await import("../lib/session-lens.js");
|
|
49
|
+
let activeProjectId;
|
|
50
|
+
if (getClaudeSessionId()) {
|
|
51
|
+
const lens = resolveActiveLens();
|
|
52
|
+
activeProjectId = lens?.projectId ?? undefined;
|
|
53
|
+
const proj = lens?.projectId ?? chalk.dim("none");
|
|
54
|
+
const ws = lens?.workspaceId ?? cfg.workspaceId ?? chalk.dim("pod-wide");
|
|
55
|
+
const sess = lens?.focusSessionId ?? chalk.dim("none");
|
|
56
|
+
console.log(` Lens : ${chalk.dim("project")} ${proj} · ${chalk.dim("ws")} ${ws} · ${chalk.dim("session")} ${sess}`);
|
|
57
|
+
}
|
|
58
|
+
else if (cfg.workspaceId) {
|
|
59
|
+
console.log(` Workspace: ${cfg.workspaceId} ${chalk.dim("(active — use 'synap use <id>' to change)")}`);
|
|
60
|
+
}
|
|
61
|
+
// ── Projects (companies / initiatives) — the primary lens ───────────────
|
|
62
|
+
log.blank();
|
|
63
|
+
log.heading("Projects");
|
|
64
|
+
if (projList.length === 0) {
|
|
65
|
+
log.dim("No projects yet — a project is a company/initiative that ties workspaces together.");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
for (const p of projList) {
|
|
69
|
+
const isActive = p.id === activeProjectId;
|
|
70
|
+
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
71
|
+
const name = chalk.bold(String(p.name ?? p.id));
|
|
72
|
+
const id = chalk.dim(String(p.id ?? ""));
|
|
73
|
+
const status = p.status ? chalk.dim(String(p.status)) : "";
|
|
74
|
+
const homePart = p.homeWorkspace ? chalk.dim(`· ${p.homeWorkspace}`) : "";
|
|
75
|
+
console.log(` ${marker}${name} ${id} ${status}${homePart ? " " + homePart : ""}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// ── Workspaces (operational domains) ────────────────────────────────────
|
|
76
79
|
log.blank();
|
|
77
80
|
log.heading("Workspaces");
|
|
78
|
-
if (
|
|
81
|
+
if (wsList.length === 0) {
|
|
79
82
|
log.dim("No workspaces found.");
|
|
80
83
|
}
|
|
81
|
-
else {
|
|
82
|
-
for (const
|
|
84
|
+
else if (opts.details) {
|
|
85
|
+
for (const ws of wsList) {
|
|
83
86
|
const isActive = ws.id === cfg.workspaceId;
|
|
84
87
|
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
85
88
|
const name = chalk.bold(String(ws.name ?? ws.id));
|
|
86
|
-
const id = chalk.dim(String(ws.id ?? "")
|
|
87
|
-
const count =
|
|
88
|
-
? chalk.dim(`${
|
|
89
|
+
const id = chalk.dim(String(ws.id ?? ""));
|
|
90
|
+
const count = ws.entityCount > 0
|
|
91
|
+
? chalk.dim(`${ws.entityCount} entities`)
|
|
89
92
|
: chalk.dim("empty");
|
|
90
|
-
log
|
|
93
|
+
console.log(` ${marker}${name} ${id} ${count}`);
|
|
91
94
|
if (ws.description)
|
|
92
95
|
log.dim(` ${String(ws.description)}`);
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
if (ws.onboarding?.goal && ws.entityCount === 0) {
|
|
97
|
+
log.dim(` ${chalk.cyan("→ onboard:")} ${String(ws.onboarding.goal)}`);
|
|
98
|
+
}
|
|
99
|
+
const profiles = ws.profiles ?? [];
|
|
100
|
+
if (profiles.length > 0) {
|
|
101
|
+
const slugs = profiles
|
|
102
|
+
.map((p) => p.slug)
|
|
96
103
|
.filter(Boolean)
|
|
97
104
|
.slice(0, 8)
|
|
98
105
|
.join(chalk.dim(", "));
|
|
99
|
-
log.dim(` profiles: ${slugs}${
|
|
106
|
+
log.dim(` profiles: ${slugs}${profiles.length > 8 ? chalk.dim(" …") : ""}`);
|
|
100
107
|
}
|
|
101
108
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
// Light: name + id + domain (operational-domain label = workspaceSubtype
|
|
112
|
+
// falling back to workspaceType, resolved server-side).
|
|
113
|
+
for (const ws of wsList) {
|
|
114
|
+
const isActive = ws.id === cfg.workspaceId;
|
|
115
|
+
const marker = isActive ? chalk.green("▶ ") : " ";
|
|
116
|
+
const name = chalk.bold(String(ws.name ?? ws.id));
|
|
117
|
+
const id = chalk.dim(String(ws.id ?? ""));
|
|
118
|
+
const domain = ws.domain ? chalk.dim(String(ws.domain)) : "";
|
|
119
|
+
console.log(` ${marker}${name} ${id} ${domain}`);
|
|
105
120
|
}
|
|
121
|
+
log.blank();
|
|
122
|
+
log.dim("Workspaces are operational domains; run 'synap orient --details' for profiles + entity counts.");
|
|
106
123
|
}
|
|
107
|
-
// ── Capabilities block ─────────────────────────────────────────────────
|
|
108
|
-
log.blank();
|
|
109
|
-
log.heading("Capabilities");
|
|
110
|
-
console.log(` ${chalk.cyan("Graph traversal")} synap graph --entity <id> --depth 2`);
|
|
111
|
-
console.log(` ${chalk.cyan("Event chain")} synap events --entity <id>`);
|
|
112
|
-
console.log(` ${chalk.cyan("Subscribe")} synap subscribe --event entity.*`);
|
|
113
|
-
console.log(` ${chalk.cyan("Session context")} synap context`);
|
|
114
|
-
console.log(` ${chalk.cyan("Automations")} synap automation list`);
|
|
115
|
-
console.log(` ${chalk.cyan("Views")} synap list views --type whiteboard · synap view create --type kanban --profile task`);
|
|
116
|
-
console.log(` ${chalk.cyan("Governance")} synap proposals list`);
|
|
117
124
|
log.blank();
|
|
118
|
-
log.dim("
|
|
125
|
+
log.dim("Lenses compose — a project spans workspaces; a workspace spans projects. Omit them to stay pod-wide.");
|
|
126
|
+
renderNextSteps(FLOW.afterOrient());
|
|
119
127
|
}
|
|
120
128
|
catch (e) {
|
|
121
|
-
|
|
129
|
+
renderHubError(e);
|
|
122
130
|
process.exit(1);
|
|
123
131
|
}
|
|
124
132
|
}
|
|
@@ -129,8 +137,7 @@ export async function useWorkspace(workspaceId, opts) {
|
|
|
129
137
|
const userId = await resolveUserId(cfg);
|
|
130
138
|
// Verify the workspace exists and is accessible
|
|
131
139
|
const res = await hubGet("/workspaces", {}, cfg);
|
|
132
|
-
const
|
|
133
|
-
const list = Array.isArray(workspaces) ? workspaces : [];
|
|
140
|
+
const list = unwrapList(res, ["workspaces"]);
|
|
134
141
|
const match = list.find((w) => w.id === workspaceId || String(w.name).toLowerCase() === workspaceId.toLowerCase());
|
|
135
142
|
if (!match) {
|
|
136
143
|
const names = list.map((w) => `${String(w.name ?? w.id)}`).join(", ");
|
|
@@ -139,16 +146,26 @@ export async function useWorkspace(workspaceId, opts) {
|
|
|
139
146
|
log.dim(`Available: ${names}`);
|
|
140
147
|
process.exit(1);
|
|
141
148
|
}
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
// In a Claude Code session, scope to THIS session's lens (so concurrent
|
|
150
|
+
// sessions can be on different workspaces). Otherwise set the global default.
|
|
151
|
+
const { getClaudeSessionId, writeLens } = await import("../lib/session-lens.js");
|
|
152
|
+
const claudeSession = getClaudeSessionId();
|
|
153
|
+
if (claudeSession) {
|
|
154
|
+
writeLens(claudeSession, { workspaceId: String(match.id) });
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const { setActiveWorkspaceId } = await import("../lib/pod.js");
|
|
158
|
+
setActiveWorkspaceId(String(match.id));
|
|
159
|
+
}
|
|
144
160
|
if (opts.json) {
|
|
145
|
-
console.log(JSON.stringify({ workspaceId: match.id, name: match.name }, null, 2));
|
|
161
|
+
console.log(JSON.stringify({ workspaceId: match.id, name: match.name, scope: claudeSession ? "session" : "global" }, null, 2));
|
|
146
162
|
return;
|
|
147
163
|
}
|
|
148
|
-
|
|
164
|
+
const scopeNote = claudeSession ? chalk.dim(" (this session)") : "";
|
|
165
|
+
log.success(`Now in workspace: ${chalk.bold(String(match.name ?? match.id))} ${chalk.dim(String(match.id ?? ""))}${scopeNote}`);
|
|
149
166
|
}
|
|
150
167
|
catch (e) {
|
|
151
|
-
|
|
168
|
+
renderHubError(e);
|
|
152
169
|
process.exit(1);
|
|
153
170
|
}
|
|
154
171
|
}
|
|
@@ -157,8 +174,7 @@ export async function listWorkspaces(opts) {
|
|
|
157
174
|
try {
|
|
158
175
|
const cfg = await resolveHubConfig(opts);
|
|
159
176
|
const res = await hubGet("/workspaces", {}, cfg);
|
|
160
|
-
const
|
|
161
|
-
const list = Array.isArray(workspaces) ? workspaces : [];
|
|
177
|
+
const list = unwrapList(res, ["workspaces"]);
|
|
162
178
|
if (opts.json) {
|
|
163
179
|
console.log(JSON.stringify({ workspaces: list }, null, 2));
|
|
164
180
|
return;
|
|
@@ -173,7 +189,7 @@ export async function listWorkspaces(opts) {
|
|
|
173
189
|
}
|
|
174
190
|
}
|
|
175
191
|
catch (e) {
|
|
176
|
-
|
|
192
|
+
renderHubError(e);
|
|
177
193
|
process.exit(1);
|
|
178
194
|
}
|
|
179
195
|
}
|
|
@@ -183,14 +199,23 @@ export async function listEntities(opts) {
|
|
|
183
199
|
const cfg = await resolveHubConfig(opts);
|
|
184
200
|
const userId = await resolveUserId(cfg);
|
|
185
201
|
const limit = parseLimit(opts.limit, 20);
|
|
202
|
+
const workspaceId = opts.workspace ?? cfg.workspaceId;
|
|
203
|
+
// --role needs a workspace to resolve facet scope (see browseEntities);
|
|
204
|
+
// without one the filter is silently dropped and "no entities" would lie.
|
|
205
|
+
if (opts.role && !workspaceId) {
|
|
206
|
+
throw new Error("--role needs an active workspace to resolve the role. Run 'synap use <workspace>' or pass --workspace <id>.");
|
|
207
|
+
}
|
|
186
208
|
const res = await hubGet("/entities", {
|
|
187
209
|
userId,
|
|
188
|
-
workspaceId
|
|
210
|
+
workspaceId,
|
|
189
211
|
profileSlug: opts.profile,
|
|
212
|
+
// Browse-by-role: the list route resolves facet scope from the
|
|
213
|
+
// `workspaceId` QUERY PARAM (already threaded above), not the
|
|
214
|
+
// X-Workspace-Id header — verified against the live pod.
|
|
215
|
+
facetSlug: opts.role,
|
|
190
216
|
limit,
|
|
191
217
|
}, cfg);
|
|
192
|
-
const
|
|
193
|
-
const list = Array.isArray(entities) ? entities : [];
|
|
218
|
+
const list = unwrapList(res, ["entities"]);
|
|
194
219
|
if (opts.json) {
|
|
195
220
|
console.log(JSON.stringify({ entities: list, count: list.length, limit, truncated: list.length === limit }, null, 2));
|
|
196
221
|
return;
|
|
@@ -206,8 +231,7 @@ export async function listEntities(opts) {
|
|
|
206
231
|
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
207
232
|
type: opts.profile,
|
|
208
233
|
}, cfg);
|
|
209
|
-
const views = viewsRes
|
|
210
|
-
?? (Array.isArray(viewsRes) ? viewsRes : []);
|
|
234
|
+
const views = unwrapList(viewsRes, ["views"]);
|
|
211
235
|
if (views.length > 0) {
|
|
212
236
|
log.blank();
|
|
213
237
|
log.info(`'${opts.profile}' is a ${chalk.bold("view type")}, not an entity profile — found ${views.length} view${views.length !== 1 ? "s" : ""}.`);
|
|
@@ -227,7 +251,8 @@ export async function listEntities(opts) {
|
|
|
227
251
|
const e = entity;
|
|
228
252
|
const name = String(e.title ?? e.id ?? "");
|
|
229
253
|
const profile = e.profileSlug ?? e.profile ?? e.type ?? "";
|
|
230
|
-
|
|
254
|
+
// Full id — this is the handle `synap get entity <id>` expects next.
|
|
255
|
+
const id = String(e.id ?? "");
|
|
231
256
|
log.info(`${name} ${chalk.dim(`(${profile})`)} — ${chalk.dim(id)}`);
|
|
232
257
|
}
|
|
233
258
|
if (list.length === limit) {
|
|
@@ -235,12 +260,15 @@ export async function listEntities(opts) {
|
|
|
235
260
|
}
|
|
236
261
|
}
|
|
237
262
|
catch (e) {
|
|
238
|
-
|
|
263
|
+
renderHubError(e);
|
|
239
264
|
process.exit(1);
|
|
240
265
|
}
|
|
241
266
|
}
|
|
242
267
|
// ─── getEntity ────────────────────────────────────────────────────────────────
|
|
243
268
|
export async function getEntity(id, opts) {
|
|
269
|
+
// `synap ask`/`synap list entities` now print full UUIDs, so an 8-char
|
|
270
|
+
// value here is almost always a leftover short id from before this fix.
|
|
271
|
+
requireFullId(id, "entity", chalk, log);
|
|
244
272
|
try {
|
|
245
273
|
const cfg = await resolveHubConfig(opts);
|
|
246
274
|
const userId = await resolveUserId(cfg);
|
|
@@ -263,64 +291,7 @@ export async function getEntity(id, opts) {
|
|
|
263
291
|
}
|
|
264
292
|
}
|
|
265
293
|
catch (e) {
|
|
266
|
-
|
|
267
|
-
process.exit(1);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
// ─── noteData ─────────────────────────────────────────────────────────────────
|
|
271
|
-
export async function noteData(text, opts) {
|
|
272
|
-
try {
|
|
273
|
-
const cfg = await resolveHubConfig(opts);
|
|
274
|
-
const userId = await resolveUserId(cfg);
|
|
275
|
-
// A `note` is the human raw-inbox primitive ("dump now, structure later") —
|
|
276
|
-
// it lands in the active workspace, NOT a private agent-memory ws (that lane
|
|
277
|
-
// was removed). The AI should never write a note: structuring is its job, so
|
|
278
|
-
// it uses `synap capture` (structured) instead.
|
|
279
|
-
const workspaceId = cfg.workspaceId;
|
|
280
|
-
if (!workspaceId) {
|
|
281
|
-
console.error(chalk.red("No workspace set. Run: synap use <workspace-id>"));
|
|
282
|
-
process.exit(1);
|
|
283
|
-
}
|
|
284
|
-
const res = await hubPost("/entities", {
|
|
285
|
-
userId,
|
|
286
|
-
profileSlug: "note",
|
|
287
|
-
title: text.slice(0, 200),
|
|
288
|
-
workspaceId,
|
|
289
|
-
// The `note` profile requires a `content` property — carry the full text
|
|
290
|
-
// (title is truncated). Without this the hub rejects the write (HTTP 500).
|
|
291
|
-
properties: {
|
|
292
|
-
content: text,
|
|
293
|
-
...(opts.context ? { sourceEntityId: opts.context } : {}),
|
|
294
|
-
},
|
|
295
|
-
}, cfg);
|
|
296
|
-
const isProposed = res.status === "proposed" || Boolean(res.proposalId);
|
|
297
|
-
const report = {
|
|
298
|
-
lane: "work",
|
|
299
|
-
workspaceId,
|
|
300
|
-
workspaceName: await resolveWorkspaceName(workspaceId, cfg),
|
|
301
|
-
governance: isProposed ? "proposed" : "auto",
|
|
302
|
-
};
|
|
303
|
-
if (opts.json) {
|
|
304
|
-
if (isProposed) {
|
|
305
|
-
console.log(JSON.stringify({ proposed: true, proposalId: res.proposalId ?? res.id, ...laneJsonFields(report) }, null, 2));
|
|
306
|
-
}
|
|
307
|
-
else {
|
|
308
|
-
console.log(JSON.stringify({ id: res.id, stored: true, ...laneJsonFields(report) }, null, 2));
|
|
309
|
-
}
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
if (isProposed) {
|
|
313
|
-
log.warn(`Queued for approval (proposal: ${String(res.proposalId ?? "")})`);
|
|
314
|
-
if (res.reviewUrl)
|
|
315
|
-
log.dim(` Review: ${String(res.reviewUrl)}`);
|
|
316
|
-
}
|
|
317
|
-
else {
|
|
318
|
-
log.success(`Note saved: "${text.slice(0, 80)}" ${chalk.dim(String(res.id ?? "").slice(0, 8))}`);
|
|
319
|
-
}
|
|
320
|
-
console.log(" " + formatLaneLine(report));
|
|
321
|
-
}
|
|
322
|
-
catch (e) {
|
|
323
|
-
console.error(chalk.red("Error: " + e.message));
|
|
294
|
+
renderHubError(e);
|
|
324
295
|
process.exit(1);
|
|
325
296
|
}
|
|
326
297
|
}
|
|
@@ -356,18 +327,75 @@ function formatAskItem(substrate, item) {
|
|
|
356
327
|
? chalk.dim(" — " +
|
|
357
328
|
(desc.length > 90 ? desc.slice(0, 87) + "…" : desc).replace(/\s+/g, " "))
|
|
358
329
|
: "";
|
|
359
|
-
|
|
330
|
+
// Full id trails at the end (never truncated — it's what `synap get entity`
|
|
331
|
+
// expects next) so it doesn't push the snippet off-screen on a narrow terminal.
|
|
332
|
+
return `${title} ${chalk.dim(`[${type}]`)}${snippet} ${chalk.dim(id)}`;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Render the A/B ranker diagnostic: baseline vs Horizon top-N side-by-side,
|
|
336
|
+
* then the diff. Comparison is by RANK POSITION (not score magnitude) — the two
|
|
337
|
+
* strategies score on different scales, so only the ordering is comparable.
|
|
338
|
+
*/
|
|
339
|
+
function renderComparison(query, comparison) {
|
|
340
|
+
if (!comparison) {
|
|
341
|
+
log.dim(`"${query}" → no ranker comparison returned (semantic pool empty?).`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const { baseline, horizon, diff } = comparison;
|
|
345
|
+
const n = Math.max(baseline.length, horizon.length);
|
|
346
|
+
log.dim(`"${query}" → A/B ranker comparison (by RANK, not score magnitude)`);
|
|
347
|
+
log.blank();
|
|
348
|
+
// Side-by-side: rank · title for each column.
|
|
349
|
+
const trunc = (s, w) => (s.length > w ? s.slice(0, w - 1) + "…" : s).padEnd(w, " ");
|
|
350
|
+
const COL = 38;
|
|
351
|
+
log.info(" " + chalk.bold("BASELINE".padEnd(COL + 5)) + chalk.bold("HORIZON"));
|
|
352
|
+
for (let i = 0; i < n; i++) {
|
|
353
|
+
const b = baseline[i];
|
|
354
|
+
const h = horizon[i];
|
|
355
|
+
const bCell = b ? `${chalk.dim(`#${b.rank}`)} ${trunc(b.title, COL)}` : "".padEnd(COL + 4);
|
|
356
|
+
const hCell = h ? `${chalk.dim(`#${h.rank}`)} ${trunc(h.title, COL)}` : "";
|
|
357
|
+
log.info(" " + bCell + " " + hCell);
|
|
358
|
+
}
|
|
359
|
+
log.blank();
|
|
360
|
+
// Diff — overlap@N + items that moved rank between the two strategies.
|
|
361
|
+
const topN = Math.max(baseline.length, horizon.length);
|
|
362
|
+
log.info(chalk.bold("DIFF") +
|
|
363
|
+
chalk.dim(` · overlap@${topN}: ${diff.overlapAtN}/${topN} shared ids`));
|
|
364
|
+
if (diff.moved.length === 0) {
|
|
365
|
+
log.dim(" No shared item changed rank between the two rankers.");
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
for (const m of diff.moved) {
|
|
369
|
+
const dir = m.horizonRank < m.baselineRank ? chalk.green("↑") : chalk.red("↓");
|
|
370
|
+
log.info(` ${dir} ${m.title} ${chalk.dim(`(baseline #${m.baselineRank} → horizon #${m.horizonRank})`)}`);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
log.blank();
|
|
360
374
|
}
|
|
361
375
|
export async function askKnowledge(query, opts) {
|
|
362
376
|
try {
|
|
363
377
|
const cfg = await resolveHubConfig(opts);
|
|
364
378
|
const limit = parseLimit(opts.limit, 10);
|
|
365
379
|
const workspaceId = opts.workspace ?? cfg.workspaceId;
|
|
366
|
-
const
|
|
380
|
+
const sessionId = opts.session ? readActiveSessionId() : undefined;
|
|
381
|
+
const res = (await hubPost("/knowledge/ask", {
|
|
382
|
+
query,
|
|
383
|
+
...(workspaceId ? { workspaceId } : {}),
|
|
384
|
+
...(sessionId ? { sessionId } : {}),
|
|
385
|
+
limit,
|
|
386
|
+
...(opts.compare ? { compare: true } : {}),
|
|
387
|
+
}, cfg));
|
|
367
388
|
if (opts.json) {
|
|
368
389
|
console.log(JSON.stringify(res, null, 2));
|
|
369
390
|
return;
|
|
370
391
|
}
|
|
392
|
+
// A/B ranker diagnostic — render the comparison and STOP. This is a
|
|
393
|
+
// ranking diff (baseline vs Horizon on the same candidate pool), not the
|
|
394
|
+
// normal answer, so it replaces the substrate listing when requested.
|
|
395
|
+
if (opts.compare) {
|
|
396
|
+
renderComparison(query, res.comparison);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
371
399
|
const routed = (res.routedTo ?? []).join(", ");
|
|
372
400
|
const verdict = res.verdict ? chalk.dim(` · ${res.verdict}`) : "";
|
|
373
401
|
// Honest routing: if the query's cue suggested one substrate but another
|
|
@@ -405,12 +433,40 @@ export async function askKnowledge(query, opts) {
|
|
|
405
433
|
}
|
|
406
434
|
log.blank();
|
|
407
435
|
}
|
|
436
|
+
// res.degraded was only ever checked as a boolean (anyErrored) above —
|
|
437
|
+
// surface which substrate(s) actually degraded, verbatim, so the answer's
|
|
438
|
+
// incompleteness is visible rather than just its existence.
|
|
439
|
+
if (res.degraded && res.degraded.length > 0) {
|
|
440
|
+
log.dim(`Degraded: ${res.degraded.join(", ")}`);
|
|
441
|
+
}
|
|
408
442
|
}
|
|
409
443
|
catch (e) {
|
|
410
|
-
|
|
444
|
+
renderHubError(e);
|
|
411
445
|
process.exit(1);
|
|
412
446
|
}
|
|
413
447
|
}
|
|
448
|
+
const refLabel = (r) => `${String(r.name ?? r.id ?? "?")}${r.profileSlug ? ` [${r.profileSlug}]` : ""}`;
|
|
449
|
+
/** Print 1-3 dim graph-impact lines for a create response. No-op if absent. */
|
|
450
|
+
function reportResolution(res) {
|
|
451
|
+
const resolution = res.resolution;
|
|
452
|
+
if (!resolution)
|
|
453
|
+
return;
|
|
454
|
+
const existing = resolution.existingSameProfile;
|
|
455
|
+
if (existing) {
|
|
456
|
+
log.dim(`⚠ an entity named "${String(existing.name ?? "?")}" already exists as profile ${String(existing.profileSlug ?? "?")} (${String(existing.id ?? "?")}) — consider updating it instead of duplicating`);
|
|
457
|
+
}
|
|
458
|
+
const autoConnected = resolution.autoConnected ?? [];
|
|
459
|
+
if (autoConnected.length > 0) {
|
|
460
|
+
const names = autoConnected.map(refLabel).join(", ");
|
|
461
|
+
log.dim(`→ auto-linked to ${autoConnected.length} existing same-name entit${autoConnected.length === 1 ? "y" : "ies"}: ${names}`);
|
|
462
|
+
}
|
|
463
|
+
// suggestions beyond what was already auto-connected
|
|
464
|
+
const autoIds = new Set(autoConnected.map((r) => r.id).filter(Boolean));
|
|
465
|
+
const suggestions = (resolution.suggestions ?? []).filter((s) => !autoIds.has(s.id));
|
|
466
|
+
if (suggestions.length > 0) {
|
|
467
|
+
log.dim(`· you may want to link: ${suggestions.map(refLabel).join(", ")}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
414
470
|
// ─── createEntity ─────────────────────────────────────────────────────────────
|
|
415
471
|
export async function createEntity(opts) {
|
|
416
472
|
try {
|
|
@@ -425,24 +481,20 @@ export async function createEntity(opts) {
|
|
|
425
481
|
properties,
|
|
426
482
|
}, cfg);
|
|
427
483
|
const entity = res;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
440
|
-
else {
|
|
441
|
-
log.success(`Created: ${opts.name} ${chalk.dim(String(entity.id ?? "").slice(0, 8))}`);
|
|
442
|
-
}
|
|
484
|
+
await reportWrite(entity, {
|
|
485
|
+
label: `Created: ${opts.name}`,
|
|
486
|
+
lane: "work",
|
|
487
|
+
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
488
|
+
cfg,
|
|
489
|
+
json: opts.json,
|
|
490
|
+
});
|
|
491
|
+
// Graph-impact feedback — human output only (the `--json` path already
|
|
492
|
+
// passed the raw response, including `resolution`, through reportWrite).
|
|
493
|
+
if (!opts.json)
|
|
494
|
+
reportResolution(entity);
|
|
443
495
|
}
|
|
444
496
|
catch (e) {
|
|
445
|
-
|
|
497
|
+
renderHubError(e);
|
|
446
498
|
process.exit(1);
|
|
447
499
|
}
|
|
448
500
|
}
|
|
@@ -456,8 +508,8 @@ export async function listProfiles(opts) {
|
|
|
456
508
|
console.error(chalk.red("No workspace set. Run: synap use <workspace-id>"));
|
|
457
509
|
process.exit(1);
|
|
458
510
|
}
|
|
459
|
-
const res = await hubGet("/profiles", { userId, workspaceId }, cfg);
|
|
460
|
-
const profiles = (res
|
|
511
|
+
const res = await hubGet("/profiles", { userId, workspaceId, ...(opts.json ? { detail: "full" } : {}) }, cfg);
|
|
512
|
+
const profiles = unwrapList(res, ["profiles"]);
|
|
461
513
|
if (opts.json) {
|
|
462
514
|
console.log(JSON.stringify(profiles, null, 2));
|
|
463
515
|
return;
|
|
@@ -470,11 +522,18 @@ export async function listProfiles(opts) {
|
|
|
470
522
|
for (const p of profiles) {
|
|
471
523
|
const scope = String(p.entityScope ?? "workspace");
|
|
472
524
|
const desc = p.description ? chalk.dim(` — ${String(p.description).slice(0, 60)}`) : "";
|
|
473
|
-
|
|
525
|
+
// A role-profile (client, partner, …) is a hat an existing entity wears
|
|
526
|
+
// via `synap facet attach` — never created as its own entity. Label it
|
|
527
|
+
// distinctly so it's never confused with a primary kind.
|
|
528
|
+
const applicableKinds = p.applicableKinds;
|
|
529
|
+
const kindLabel = p.profileKind === "role"
|
|
530
|
+
? chalk.magenta(`[Role${applicableKinds?.length ? ` of ${applicableKinds.join("/")}` : ""}]`)
|
|
531
|
+
: chalk.green("[Kind]");
|
|
532
|
+
log.info(`${chalk.bold(String(p.slug ?? ""))} ${kindLabel} ${chalk.dim(scope)}${desc}`);
|
|
474
533
|
}
|
|
475
534
|
}
|
|
476
535
|
catch (e) {
|
|
477
|
-
|
|
536
|
+
renderHubError(e);
|
|
478
537
|
process.exit(1);
|
|
479
538
|
}
|
|
480
539
|
}
|
|
@@ -491,14 +550,16 @@ export async function createRelation(opts) {
|
|
|
491
550
|
type: opts.type,
|
|
492
551
|
}, cfg);
|
|
493
552
|
const relation = res;
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
553
|
+
await reportWrite(relation, {
|
|
554
|
+
label: `Relation: ${opts.type} (${opts.source} → ${opts.target})`,
|
|
555
|
+
lane: "work",
|
|
556
|
+
workspaceId: opts.workspace ?? cfg.workspaceId,
|
|
557
|
+
cfg,
|
|
558
|
+
json: opts.json,
|
|
559
|
+
});
|
|
499
560
|
}
|
|
500
561
|
catch (e) {
|
|
501
|
-
|
|
562
|
+
renderHubError(e);
|
|
502
563
|
process.exit(1);
|
|
503
564
|
}
|
|
504
565
|
}
|
|
@@ -521,9 +582,15 @@ export async function updateEntity(id, opts) {
|
|
|
521
582
|
return;
|
|
522
583
|
}
|
|
523
584
|
log.success(`Updated: ${id}`);
|
|
585
|
+
// Graph-impact feedback — shallow immediate neighbors the edit may touch.
|
|
586
|
+
// Additive + graceful: absent on older backends, so output is unchanged.
|
|
587
|
+
const impact = entity.impact;
|
|
588
|
+
if (Array.isArray(impact) && impact.length > 0) {
|
|
589
|
+
log.dim(`→ ${impact.length} connected entit${impact.length === 1 ? "y" : "ies"} may be affected: ${impact.map(refLabel).join(", ")}`);
|
|
590
|
+
}
|
|
524
591
|
}
|
|
525
592
|
catch (e) {
|
|
526
|
-
|
|
593
|
+
renderHubError(e);
|
|
527
594
|
process.exit(1);
|
|
528
595
|
}
|
|
529
596
|
}
|