@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
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
## CLI Data Operations (Bash tool)
|
|
2
|
+
|
|
3
|
+
When Claude Code (or any agent with Bash access) is using this skill, prefer the `synap` CLI over raw HTTP calls — auth is automatic, output is clean JSON, no spinners in `--json` mode.
|
|
4
|
+
|
|
5
|
+
**Session context — set once, never repeat:**
|
|
6
|
+
|
|
7
|
+
The CLI inherits your pod + lens automatically; set them once and every later command picks them up. Do NOT pass `--pod-url`, `--api-key`, or `--workspace` on every command. Inside a Claude session, `synap use` / `synap project use` bind **this session's lens** (`~/.synap/lenses/<session_id>.json`) — so concurrent sessions stay independent; outside one, they set the global default (`~/.synap/config.json`).
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
synap pods use <profile-name> # switch active pod
|
|
11
|
+
synap use <workspace-id> # focus a workspace (this session) — captures land here; it IS the domain
|
|
12
|
+
synap project use <id> # add the project lens (composable)
|
|
13
|
+
synap lens # inspect: workspace + project + session this session resolves to
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Always orient first:**
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
synap orient --json
|
|
20
|
+
# Returns: userId, podUrl, workspaces[{id, name, slug}]
|
|
21
|
+
# Never hardcode workspace IDs — discover them here.
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Ask (the one read verb — routes across all substrates):**
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
synap ask "project ideas" --json
|
|
28
|
+
synap ask "what did Antoine decide about auth" --workspace=<id> --json
|
|
29
|
+
synap ask "how do I deploy the backend" --json # routes to procedural how-to docs
|
|
30
|
+
# Omit --workspace for pod-wide; include it to scope to one workspace.
|
|
31
|
+
# `ask` classifies intent and unions the right substrate(s) — it replaces search/recall.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Read entities:**
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
synap list workspaces --json
|
|
38
|
+
synap list entities --workspace=<id> --json
|
|
39
|
+
synap list entities --profile=task --workspace=<id> --json
|
|
40
|
+
synap get entity <id> --json
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Capturing a decision (the AI structures — it never `note`s):**
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
synap capture --type decision --claim "Use Typesense for entity search" --json
|
|
47
|
+
# Retrieve later with the one read verb: synap ask "Typesense decision"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
> `synap note` is the HUMAN's raw "dump now, structure later" inbox. As the AI, always `capture` into a lane — structuring is your job.
|
|
51
|
+
|
|
52
|
+
**Structured knowledge (durable, typed, searchable — preferred for engineering learnings):**
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Work lane (default): a domain gotcha/lesson/decision → knowledge entity in the ACTIVE workspace
|
|
56
|
+
synap capture --type gotcha --claim "Hono static routes must come before /:id" \
|
|
57
|
+
--why "First-match routing; dynamic routes eat static ones" \
|
|
58
|
+
--tags "repo:synap-backend,layer:routing" --json
|
|
59
|
+
|
|
60
|
+
synap capture --type lesson --claim "code-read ≠ runtime-true for library APIs" \
|
|
61
|
+
--evidence "tldraw 2.4.6 binding API changed silently from props.start.boundShapeId"
|
|
62
|
+
|
|
63
|
+
# A quick decision-note is a typed knowledge entry (ek_type=decision):
|
|
64
|
+
synap capture --type decision --claim "Use Typesense for entity search" \
|
|
65
|
+
--why "pgvector deferred to V1; Typesense ships now" --json
|
|
66
|
+
|
|
67
|
+
# Global lane: a runbook/best-practice that holds across ALL projects → pod-wide knowledge_keys
|
|
68
|
+
synap capture --global --type reference --claim "Always fix the canonical path, never a workaround" \
|
|
69
|
+
--key "principle:root-cause" --json
|
|
70
|
+
|
|
71
|
+
# Retrieve any of it later with the one read verb (it spans every lane):
|
|
72
|
+
synap ask "hono routing gotcha" --json
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`synap capture --type` writes a typed **`knowledge`** entity in the **active workspace** (the Work lane); `ek_type` (gotcha|lesson|decision|reference) discriminates the kind — **one store, type tags, not a residual dump**. It's workspace-scoped, so the active workspace supplies the domain — a Builder gotcha ≠ a marketing one (there is no `engineering_knowledge`). Add **`--global`** to write a pod-wide cross-cutting runbook to `knowledge_keys` instead. A formal **decision RECORD** (rationale, alternatives, superseded-by lifecycle) is a different artifact — use smart `synap capture "<free text>"` or `synap create entity --profile=decision`. Retrieve everything with `synap ask`.
|
|
76
|
+
Use `capture` for anything worth remembering across sessions and projects.
|
|
77
|
+
|
|
78
|
+
**Open (the one display door):**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
synap open <id> # resolves type automatically, opens in browser
|
|
82
|
+
synap open entity <id> # open entity detail
|
|
83
|
+
synap open proposal <id> # open proposal review
|
|
84
|
+
synap open view <id> # open a view
|
|
85
|
+
synap open cell <typeKey> # open a registered cell by typeKey
|
|
86
|
+
synap open document <id> # open a document
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The bare-ID form calls `GET /api/hub/resolve/:id` to determine the type before dispatching. Use this when you don't know what type a UUID is — `synap open <id>` always works.
|
|
90
|
+
|
|
91
|
+
**Write:**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
synap create entity --profile=note --name="Meeting notes" --workspace=<id> --json
|
|
95
|
+
synap set entity <id> --props='{"status":"done"}' --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**Multi-agent:** If `SYNAP_AGENT` env var is set, the CLI uses that named identity's API key from `~/.synap/config.json` instead of the default pod credentials. Use `synap agents list` to see configured identities.
|
|
99
|
+
|
|
100
|
+
**Rules:**
|
|
101
|
+
|
|
102
|
+
- Always use `--json` when calling from code — clean stdout, no spinners, machine-parseable
|
|
103
|
+
- Run `synap orient` first to discover workspace IDs — never hardcode them
|
|
104
|
+
- Omit `--workspace` to operate pod-wide; include it to scope to a specific workspace
|
|
105
|
+
- `synap ask` is the one read verb — it routes keyword + semantic + procedural automatically; you never choose a search backend.
|
|
106
|
+
|
|
107
|
+
---
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
## Common mistakes — core data operations
|
|
2
|
+
|
|
3
|
+
1. **Creating orphan entities.** Always connect to at least one other entity on creation. Search first; if nothing links, reconsider whether this should be memory.
|
|
4
|
+
2. **Guessing profile slugs.** Always `GET /profiles` first. `deal`, `capture`, and custom profiles may not exist in this workspace.
|
|
5
|
+
3. **Using the deprecated `type` field.** Always `profileSlug`.
|
|
6
|
+
4. **Treating `"proposed"` as an error.** It's a governance queue.
|
|
7
|
+
5. **Forcing `source` to bypass governance.** Governance is determined by the agent user + whitelist, not by `source`. Don't set it.
|
|
8
|
+
6. **Not knowing your userId.** Use `{SYNAP_USER_ID}` from the env (set by `synap connect`). Or call `GET /api/hub/users/me` → `.id` once and cache it. Never hardcode or guess.
|
|
9
|
+
7. **Skipping the search step.** Duplicates degrade the graph more than missing data.
|
|
10
|
+
8. **Forgetting that `GET /channels/personal` needs `hub-protocol.write`** scope — it's get-or-create, not a pure read.
|
|
11
|
+
9. **Routing known-structure data through free-text capture.** If you already know the profileSlug + fields, create the entity directly — smart capture can degrade to a single flat note.
|
|
12
|
+
10. **Paragraph session goals.** The goal is one line; put detail and deliverables in expectedOutputs.
|
|
13
|
+
11. **Creating a `file`/`document`-kind entity to hold text you wrote.** A pitch deck, plan, or note body you authored is `content` on a real CONTENT-kind entity (`note`, `knowledge`, a domain kind) — Synap auto-materializes it into a document. `file` is only for real uploaded bytes you actually have; an agent with no filesystem almost never needs it.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
## Content OS — the editorial model
|
|
2
|
+
|
|
3
|
+
Some workspaces run an editorial engine: `pillar`, `post`, `platform`, `newsletter`, plus the reused `campaign` and `sponsor`. Content OS is a **derived lens**, not a silo — the journey it can reason about is a function of what else exists in the pod. Understand this before proposing posts, pillars, or a content plan.
|
|
4
|
+
|
|
5
|
+
**The editorial core:**
|
|
6
|
+
|
|
7
|
+
- **`pillar`** — a recurring theme the audience knows the operator for. Two to four, not twelve. `pillar-status` (Active, Developing, Paused, Retired), `pillar-goal`, `pillar-formats`, `posting-frequency`.
|
|
8
|
+
- **`post`** — the atomic unit. `post-status` moves Idea → Briefed → In Draft → Review → Scheduled → Published → Archived. Plus `post-format`, `post-platform`, `publish-date`, `post-hook`, `post-cta`; measured by `engagement-score` and `post-reach`.
|
|
9
|
+
- **`platform`** — a publishing account (social, newsletter publication, podcast). Carries its own cadence and audience metrics.
|
|
10
|
+
- **`newsletter`** — one issue of the owned channel. `newsletter-status`, `newsletter-pillar`.
|
|
11
|
+
- **`campaign`** and **`sponsor`** — reused from marketing / foundation, not owned here.
|
|
12
|
+
|
|
13
|
+
**The journey layer (optional, additive):**
|
|
14
|
+
|
|
15
|
+
- **`journey-stage`** — where a reader is. Each stage names the belief it installs, the doubt it dissolves, and the action that advances them. Unordered _tagging_.
|
|
16
|
+
- **`series`** — an ordered curriculum, prerequisite-bearing: chapter by chapter.
|
|
17
|
+
- **`offer`** — the thing being sold. Owned by the `foundation` workspace, pod-wide. **Frequently absent — see the degradation rule.**
|
|
18
|
+
|
|
19
|
+
A post joins these through `post-stage`, `post-series`, `post-offer`; a repurposed post points at its source with `derived-from`.
|
|
20
|
+
|
|
21
|
+
**Two axes, both optional, composable:** CURRICULUM (`series` — ordered, "which chapter is this?") and AUDIENCE STAGE (`journey-stage` — an unordered tag, "where is the reader?"). A post carries at most one of each. With neither, Content OS still works exactly as a post tracker — that is a valid end state, not an incomplete one.
|
|
22
|
+
|
|
23
|
+
## The degradation rule — check before you assume
|
|
24
|
+
|
|
25
|
+
Read the world before you reason about it: `list_profiles` tells you the vocabulary actually provisioned, and the `## Pod Domains` block in your context tells you which domains exist.
|
|
26
|
+
|
|
27
|
+
- **No offer-bearing domain, no `offer` entities** → the journey is pure audience-building. **Do NOT invent commerce.** No CTA to a product that does not exist, no fabricated `offer`, no "book a call" the operator never mentioned. Reason on the curriculum and stage axes and stop there.
|
|
28
|
+
- **`foundation` exists** → bind pillars to its real `audience`, `pain-point` and `positioning` entities rather than inventing personas. A pillar aimed at a persona you made up is worse than a pillar with no audience named.
|
|
29
|
+
- **`journey-stage` / `series` / `offer` absent from `list_profiles`** → this pod runs the plain editorial model. Do not reference those slugs at all.
|
|
30
|
+
|
|
31
|
+
Absence is information, not a hole to fill.
|
|
32
|
+
|
|
33
|
+
## Pillars before posts
|
|
34
|
+
|
|
35
|
+
A creator known for two to four themes compounds; one posting about everything stays noise. If the operator hands you a dozen post ideas but cannot name the themes underneath, surface THAT before filling the calendar. Every post you propose hangs off a pillar — `post-pillar` plus a `belongs_to_pillar` relation. An unpillared post is drift.
|
|
36
|
+
|
|
37
|
+
## AI behavior — placing a post on the journey
|
|
38
|
+
|
|
39
|
+
When the operator describes a content idea, propose the post WITH its placement — never a bare title:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
POST /api/hub/entities
|
|
43
|
+
{ "userId": "{userId}", "workspaceId": "{wsId}",
|
|
44
|
+
"profileSlug": "post",
|
|
45
|
+
"title": "Why your pricing page loses the sale",
|
|
46
|
+
"properties": {
|
|
47
|
+
"post-status": "Idea",
|
|
48
|
+
"post-format": "Article",
|
|
49
|
+
"post-platform": "LinkedIn",
|
|
50
|
+
"post-pillar": "ent_pillar_positioning",
|
|
51
|
+
"post-stage": "ent_stage_evaluating"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
POST /api/hub/relations
|
|
56
|
+
{ "userId": "{userId}",
|
|
57
|
+
"sourceEntityId": "ent_post_pricing",
|
|
58
|
+
"targetEntityId": "ent_pillar_positioning",
|
|
59
|
+
"type": "belongs_to_pillar"
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Omit `post-stage` when no `journey-stage` exists, and omit `post-offer` when no `offer` exists. An empty commercial field is correct; a fabricated one is a defect. Use `derived-from` when the post is a repurpose of an existing one — one idea legitimately becomes a thread, a video, and a newsletter section.
|
|
64
|
+
|
|
65
|
+
## Gap analysis — proposing the next piece
|
|
66
|
+
|
|
67
|
+
"What should I write next" is an audit, not a brainstorm:
|
|
68
|
+
|
|
69
|
+
1. **Read the corpus** — one batched `list_entities` pass over `post` and `pillar`. Never one call per post; that is a cost failure.
|
|
70
|
+
2. **Map it** — each post to its pillar × its stage (or its place in a series). Build the grid before judging it.
|
|
71
|
+
3. **Find the holes** — a pillar with nothing at the earliest stage; a stage every pillar skips; a series that stops mid-curriculum; a pillar whose last post is months old.
|
|
72
|
+
4. **Propose the hole, not a topic** — "Pillar X has nothing that removes the pricing objection" beats "here are ten content ideas". Name the pillar, the stage, the belief to install, and the format.
|
|
73
|
+
5. **Ground it** — a proposed post cites the pillar it serves and, when `foundation` exists, the real `audience` or `pain-point` entity it answers. Otherwise it is a guess dressed as a plan.
|
|
74
|
+
|
|
75
|
+
Rank gaps by what the operator is actually known for, not what they wish they were known for.
|
|
76
|
+
|
|
77
|
+
## Resolution discipline — resolve BEFORE you create
|
|
78
|
+
|
|
79
|
+
Standard resolve-before-create applies (search once, batched, before proposing anything). Domain-specific matching keys: **platforms** resolve on handle or URL, **offers** on name, **pillars** on theme. Never placeholder — no pillar named "General", no `platform` for an account the operator doesn't have, no `offer` invented so a post has something to sell. Every post you propose attaches to at least a pillar; a post with no pillar and no stage is a note, not content.
|
|
80
|
+
|
|
81
|
+
## Kind vs facets, and governed writes
|
|
82
|
+
|
|
83
|
+
`sponsor` is a role-profile (`profileKind: role`) — per ENTITY MODEL, resolve the real company first, then `attach_facet`; a sponsoring company is never a second entity, and graph links attach to the parent, not the facet.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## The Creative Loop — do once, then crystallize to reusable config
|
|
2
|
+
|
|
3
|
+
The core rhythm of real work in Synap: **do the thing once by hand, then crystallize what worked into reusable configuration.** You author; the user curates. Every crystallization is governed — a `proposed` result is the normal, successful outcome, never an error.
|
|
4
|
+
|
|
5
|
+
The loop has three moves that compound. Each takes a one-off act and, if it's worth repeating, turns it into standing structure:
|
|
6
|
+
|
|
7
|
+
| Do-once (author) | → Crystallize (curate) | Tool |
|
|
8
|
+
| --------------------------------------- | ----------------------------------- | ----------------------------- |
|
|
9
|
+
| Work a multi-step goal in a **session** | → a **playbook** (the process) | `promote_session_to_playbook` |
|
|
10
|
+
| Show a result in a **cell** | → a **renderer** for an entity type | `promote_cell_to_renderer` |
|
|
11
|
+
|
|
12
|
+
### 1. Open a session for real work
|
|
13
|
+
|
|
14
|
+
When the task is a unit of work with a deliverable — research, a build, an investigation, a sprint — and there's no active session, **`start_session`** with a clear `goal` and `expectedOutputs`. The session is the spine that accrues results (see the focus-sessions skill). Don't open one for a one-shot lookup or a casual reply.
|
|
15
|
+
|
|
16
|
+
### 2. Create a cell to REPORT — don't dump data into chat
|
|
17
|
+
|
|
18
|
+
When you have something to _show_ the user — a list of leads, a summary, a comparison, a chart — author a **cell** with `create_cell` instead of pasting rows into the message.
|
|
19
|
+
|
|
20
|
+
- **Declare the data intent in `rendererSource`; do NOT pre-fetch.** Cells use a dynamic data-binding SDK: you describe what the cell needs (e.g. "the open leads in this workspace"), and the runtime binds the live data at render time. Never fetch rows yourself and inline them — that snapshot goes stale and defeats the cell.
|
|
21
|
+
- Keep one cell to one job. A good, focused cell is the raw material for the next move.
|
|
22
|
+
|
|
23
|
+
### 3. Promote a good cell to a renderer — recurring presentation
|
|
24
|
+
|
|
25
|
+
When a cell is a _good, recurring way to present a whole entity type or step_ — e.g. every `bookmark`'s detail view, every `lead`'s list row — promote it with `promote_cell_to_renderer`:
|
|
26
|
+
|
|
27
|
+
- Pick the `profileSlug` (the entity type), the `slot` (`list` | `detail` | `dashboard`), and the `cellKey` from `create_cell`.
|
|
28
|
+
- This is **governed**: for you it returns `{ status: "proposed", proposalId }`. That is the point — you author the renderer, the user reviews and curates it before it becomes every entity's view. Surface the proposal plainly ("I've proposed this as the detail view for bookmarks — review it when you like"), don't treat it as a failure.
|
|
29
|
+
- Use `scope: "pod"` only when the presentation should apply in every workspace; default to workspace scope.
|
|
30
|
+
|
|
31
|
+
### 4. Promote a finished session to a playbook — recurring process
|
|
32
|
+
|
|
33
|
+
When the session is done **and the work was a repeatable process** (not a one-off), promote it with `promote_session_to_playbook({ sessionId })`. This captures the goal, tasks, expected outputs, and steps as a reusable session template — so next time the process starts pre-built instead of from scratch.
|
|
34
|
+
|
|
35
|
+
- Do this at the _end_, once the promised outputs are produced and verified.
|
|
36
|
+
- Judge repeatability honestly: a bespoke, never-again investigation is not a playbook. A "weekly competitor scan" or "new-client onboarding" is.
|
|
37
|
+
- Governed like the others — `promoted` (applied) or `proposed` (awaiting review) are both normal.
|
|
38
|
+
|
|
39
|
+
### The symmetry
|
|
40
|
+
|
|
41
|
+
Sessions and cells are the two things you _do_; playbooks and renderers are the two things you _keep_. The instinct to build: **first do it once concretely, watch it work, then offer to crystallize it** — and let the user decide what becomes standing config. Never crystallize speculatively before the one-off has proven itself.
|
|
42
|
+
|
|
43
|
+
This is escalation ladder **L4**: crystallize only after proof. Blocked/missing structure climbs L2→L3 first (`escalation-ladder.md`); L4 is the success path, not a substitute for discovery.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
## CRM Workspaces — 4-Entity Model
|
|
2
|
+
|
|
3
|
+
Some workspaces use a CRM data structure with four entities: `person` and `company` (identity records), `deal` (pipeline record), and `client` (post-win relationship marker). Understand this pattern when proposing lead captures, deal updates, or campaign membership.
|
|
4
|
+
|
|
5
|
+
**The model:**
|
|
6
|
+
|
|
7
|
+
- **`person` + `company`** — Identity only, no sales state. Persist across deals.
|
|
8
|
+
- **`deal`** — Pipeline record with `dealStage` property (lead, contacted, qualifying, proposal, negotiating, won, lost, inactive). Represents what people often call a "lead" (when stage=lead). Linked to person/company via `linked_to_deal` relation.
|
|
9
|
+
- **`client`** — Post-win relationship marker. Created automatically when deal transitions to stage=won. Status: active, paused, or churned. Linked via `is_client` (party → client) and `produced_by_deal` (deal → client).
|
|
10
|
+
- **`journey`** — Documents anchored to a deal (not a person). Linked via `has_journey`.
|
|
11
|
+
|
|
12
|
+
**AI behavior — lead capture:**
|
|
13
|
+
|
|
14
|
+
When the user describes a lead (inbound person, prospect, or company lead), propose the full bundle:
|
|
15
|
+
|
|
16
|
+
1. Create `person` entity (if not exists) with email, role, company name
|
|
17
|
+
2. Create `company` entity (if not exists)
|
|
18
|
+
3. Create `deal` entity with `dealStage: "lead"` and `estimatedValue` (if known)
|
|
19
|
+
4. Create `linked_to_deal` relation connecting person/company to deal
|
|
20
|
+
|
|
21
|
+
Never create a person with a sales-state flag. The deal is the lead container.
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
POST /api/hub/entities
|
|
25
|
+
{ "userId": "{userId}", "workspaceId": "{wsId}",
|
|
26
|
+
"profileSlug": "person",
|
|
27
|
+
"title": "Alice Johnson",
|
|
28
|
+
"properties": { "email": "alice@acme.com", "role": "VP Engineering" }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
POST /api/hub/entities
|
|
32
|
+
{ "userId": "{userId}", "workspaceId": "{wsId}",
|
|
33
|
+
"profileSlug": "deal",
|
|
34
|
+
"title": "Acme prospect",
|
|
35
|
+
"properties": { "dealStage": "lead", "estimatedValue": 50000 }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
POST /api/hub/relations
|
|
39
|
+
{ "userId": "{userId}",
|
|
40
|
+
"sourceEntityId": "ent_person_alice",
|
|
41
|
+
"targetEntityId": "ent_deal_acme",
|
|
42
|
+
"type": "linked_to_deal"
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**AI behavior — moving deals to won:**
|
|
47
|
+
|
|
48
|
+
When a deal transitions to `dealStage: "won"`, also propose client creation if not yet linked:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
PATCH /api/hub/entities/ent_deal_acme
|
|
52
|
+
{ "properties": { "dealStage": "won" } }
|
|
53
|
+
|
|
54
|
+
POST /api/hub/entities
|
|
55
|
+
{ "userId": "{userId}", "workspaceId": "{wsId}",
|
|
56
|
+
"profileSlug": "client",
|
|
57
|
+
"title": "Acme (active)",
|
|
58
|
+
"properties": { "clientStatus": "active" }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
POST /api/hub/relations
|
|
62
|
+
{ "userId": "{userId}",
|
|
63
|
+
"sourceEntityId": "ent_person_alice",
|
|
64
|
+
"targetEntityId": "ent_client_acme",
|
|
65
|
+
"type": "is_client"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
POST /api/hub/relations
|
|
69
|
+
{ "userId": "{userId}",
|
|
70
|
+
"sourceEntityId": "ent_deal_acme",
|
|
71
|
+
"targetEntityId": "ent_client_acme",
|
|
72
|
+
"type": "produced_by_deal"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**AI behavior — campaign membership:**
|
|
77
|
+
|
|
78
|
+
When the user describes campaign members (segment for outreach, tracking, or automation), use polymorphic `member_of` relations. Members can be persons, companies, or deals:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
POST /api/hub/relations
|
|
82
|
+
{ "userId": "{userId}",
|
|
83
|
+
"sourceEntityId": "ent_person_alice",
|
|
84
|
+
"targetEntityId": "ent_campaign_enterprise",
|
|
85
|
+
"type": "member_of"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Same relation type, different entity type
|
|
89
|
+
POST /api/hub/relations
|
|
90
|
+
{ "userId": "{userId}",
|
|
91
|
+
"sourceEntityId": "ent_deal_acme",
|
|
92
|
+
"targetEntityId": "ent_campaign_enterprise",
|
|
93
|
+
"type": "member_of"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Property names:**
|
|
98
|
+
|
|
99
|
+
- `dealStage` (not `crmStatus` or `status`) — values: lead, contacted, qualifying, proposal, negotiating, won, lost, inactive
|
|
100
|
+
- `clientStatus` (post-win only) — values: active, paused, churned
|
|
101
|
+
- Identities (person, company) carry no sales state
|
|
102
|
+
|
|
103
|
+
**Why separate identity from state:**
|
|
104
|
+
|
|
105
|
+
This model enables renewals (new deal linking to existing client), multi-stakeholder deals (multiple `linked_to_deal` relations per deal), campaigns with mixed entity types (persons + companies + deals as members), and clean churn tracking. It matches Synap's core pattern: entities + relations = graph.
|
|
106
|
+
|
|
107
|
+
## Resolution discipline — resolve BEFORE you create
|
|
108
|
+
|
|
109
|
+
Extracting people/companies from a digest, an email/DM thread, or notes is a RESOLUTION problem, not a creation problem. Follow this method every time (it is generic — the specific team roster and known aliases are DATA you fetch, never hardcoded):
|
|
110
|
+
|
|
111
|
+
1. **Search first, once (batched).** Before proposing any person/company, run a SINGLE batched query (`search_unified`, plus `list_entities` if needed) that covers ALL candidate names, handles, emails and aliases at once. Never run one query per candidate — that is a cost failure.
|
|
112
|
+
2. **Reuse on match → add an alias.** If a candidate matches an existing entity, reference the existing entity by its real id (e.g. `existingEntityId` on `propose_entity_graph`) and add the newly-seen surface form (a handle, an alternate spelling) to the entity's `aliases` — do NOT create a second `person`/`company`. The `person` profile carries `email`, `discord-handle` and `aliases` for exactly this.
|
|
113
|
+
3. **Never placeholder.** Never mint an entity whose identity is unstated — "Not publicly disclosed", "unknown", "TBD", an empty name, or a bare handle with no person behind it. Fold that unstated thing into the description of a related entity instead.
|
|
114
|
+
4. **Team is not a contact.** Internal senders — your own side of a `client-comms` thread (the agency's own team) — are NEVER captured as the client's contacts. Only the external party becomes a person/company/deal. Team roster may appear in `orient.teamRoster` — treat as internal.
|
|
115
|
+
5. **Connect the graph.** Every entity you propose should attach via at least one relation (person `works_at` company, person `linked_to_deal` deal, …). A name mentioned only in passing, with no relation and no stated identity, is not worth capturing as its own entity.
|
|
116
|
+
|
|
117
|
+
An extraction that creates a duplicate "Sarah Chen", or a `person` titled "Unknown sender", is a failure — resolve, reuse, and alias instead.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Diagnosing what an AI did — the runs door
|
|
2
|
+
|
|
3
|
+
When a capture, automation, playbook, or session **didn't do what you (or the user) expected** — a facet wasn't attached, an entity landed in the wrong workspace, a step failed silently — do **not** guess or apologize. Every AI run leaves a trace. Read it.
|
|
4
|
+
|
|
5
|
+
## The one tool
|
|
6
|
+
|
|
7
|
+
`synap_diagnose` — the unified view of what an AI did across flows.
|
|
8
|
+
|
|
9
|
+
- **No args** → the recent run feed (automation · playbook · capture · session), newest first. Each run has an `id`, `flowType`, `status`, and `flowName`.
|
|
10
|
+
- **`runId` + `flowType`** → that run's **activity timeline**. For a **capture** run this is its decision + trace events: for each thing that was dropped/coerced, a machine-readable `reason` **and an actionable `fixHint`**.
|
|
11
|
+
|
|
12
|
+
(CLI equivalent for the operator: `synap diagnose` and `synap diagnose <captureId> --flow capture`.)
|
|
13
|
+
|
|
14
|
+
## The reflex
|
|
15
|
+
|
|
16
|
+
> "The capture didn't attach the client role" → `synap_diagnose({ runId: <captureId>, flowType: "capture" })` → read the `capture_trace` rows → act on the `fixHint`.
|
|
17
|
+
|
|
18
|
+
A capture's `id` **is** its correlationId — the same id stamped on the entities it created and returned to you as `captureId`. So you always have the key to diagnose your own last capture.
|
|
19
|
+
|
|
20
|
+
## Reading a capture trace
|
|
21
|
+
|
|
22
|
+
Each `capture_trace` activity item names a pipeline stage (`component`), why it stopped (`reason`), and what to do (`fixHint`). The common ones:
|
|
23
|
+
|
|
24
|
+
| reason | what happened | what to do |
|
|
25
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `not_in_creatable_catalog` | a role/kind you asked to create isn't a creatable entity kind — it's a **facet** (client, partner, prospect, investor…) | resolve the real entity first, then `attach_facet` for the role — never a second entity for a hat |
|
|
27
|
+
| `kind_mismatch` | the facet's `applicableKinds` didn't include the target entity's kind | attach the role to an entity of a kind the role applies to |
|
|
28
|
+
| `slug_coerce` | a profileSlug was normalized/renamed to the canonical one | use the canonical slug next time (see `list_profiles`) |
|
|
29
|
+
| `materialize_skip` | an operation was skipped (dedup or a missing dependency) | check the dedup match; re-capture only what's genuinely new |
|
|
30
|
+
|
|
31
|
+
If a run carries a `channelId` (playbook / session / automation), its message-level story lives in that channel — the timeline points you there rather than duplicating it.
|
|
32
|
+
|
|
33
|
+
## Why this matters
|
|
34
|
+
|
|
35
|
+
The point of the flywheel is that mistakes are **visible and fixable**, not silent. If you can see what happened, you can correct it — and every correction teaches the routing. Reach for `synap_diagnose` before you conclude "it didn't work."
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# digesting-a-channel
|
|
2
|
+
|
|
3
|
+
You are digesting a chat channel — reading a window of human messages and deciding what, if anything, is worth the team's attention. You are an ADVISOR, not a bookkeeper. Surface signal; do not log every message into the database.
|
|
4
|
+
|
|
5
|
+
## What a digest is for
|
|
6
|
+
|
|
7
|
+
Read the whole window, then answer one question: **what here genuinely matters to the team?** A decision that got made, an ask with a deadline, a new opportunity, a link worth keeping, a task someone implicitly took on, a shift in a live piece of work. Most channel chatter is noise — greetings, banter, thinking-out-loud. If nothing rises above noise, say so and stop. An honest "nothing to surface" beats a wall of manufactured entities.
|
|
8
|
+
|
|
9
|
+
## Structure signal into whatever shape actually fits
|
|
10
|
+
|
|
11
|
+
Do NOT assume this channel is a CRM. Do NOT reach for a contacts/notes/links template by reflex. Look at the signal and pick the Synap shape that truly matches it:
|
|
12
|
+
|
|
13
|
+
- an **idea** or **decision** — a direction the team settled on, an ask, a scope change
|
|
14
|
+
- a **website / link / resource** worth keeping
|
|
15
|
+
- a **deal** or **partner** — a real new opportunity or relationship (only if that is genuinely what surfaced)
|
|
16
|
+
- a **task** — a concrete next action someone owns, with a due date if one was stated
|
|
17
|
+
- an **advancement on a workflow / playbook** — a stage moved or a step completed on work already live in the pod
|
|
18
|
+
|
|
19
|
+
`list_profiles` first when you are unsure what shapes exist. Match the signal to the shape; never force the signal into a shape you had already decided on.
|
|
20
|
+
|
|
21
|
+
## Resolve identity before you create
|
|
22
|
+
|
|
23
|
+
Every person, company, deal, or resource you are about to propose may already exist. Resolve first, create only what is new. Match on STRONG signals — email, phone, url, handle — not a fuzzy name. Run ONE batched search over all candidates, reuse on match (add the newly-seen handle or spelling as an alias), and mint an entity only for something genuinely absent. The full resolve → reuse → alias discipline in `crm.md` applies here verbatim.
|
|
24
|
+
|
|
25
|
+
## When the channel is UNBOUND — classify it and PROPOSE a bind
|
|
26
|
+
|
|
27
|
+
A channel that is **not yet bound to any entity** (no `contextObjectId`, no `branchPurpose`) is a different job from a normal digest. Before you mine it for signal, answer a prior question: **what IS this channel, and which entity does it belong to?** This is the "I think #acme is a client — link it?" affordance.
|
|
28
|
+
|
|
29
|
+
Work it in this order — identity FIRST, classification, then propose:
|
|
30
|
+
|
|
31
|
+
1. **Read the window + the channel NAME.** The name (`acme`, `weex-partnership`, `general`, `eng-team`) is often the strongest single signal; the messages confirm or correct it. Who posts, what they talk about, whether it reads client-facing or internal.
|
|
32
|
+
2. **Resolve the entity FIRST — do NOT mint a duplicate.** Match the channel to something that already exists in the pod on STRONG signals — the name, a domain/email/url mentioned, a handle — using `resolve_identity` / a batched search. Only if nothing genuinely matches do you consider a new entity, and even then propose the entity through the normal capture door, never a throwaway. The whole point of binding is to point the channel at the REAL thing; binding to a fabricated duplicate is worse than not binding at all.
|
|
33
|
+
3. **Classify what the channel is** — pick the one that fits:
|
|
34
|
+
- **client** — a client-facing channel (mixes their people and ours). Suggests `branchPurpose: "client-comms"`.
|
|
35
|
+
- **partner** — a partner/vendor relationship channel. Suggests `branchPurpose` like `"partner"` (or leave to the human).
|
|
36
|
+
- **internal team** — everyone here is OUR team; ops/eng/planning. Suggests `branchPurpose: "team"`.
|
|
37
|
+
- **project** — work-scoped, cross-cutting. Suggests a project-oriented purpose (or `"team"` if internal).
|
|
38
|
+
4. **Emit ONE governed bind proposal** with `propose_channel_bind` — `channelId` (the Synap channel UUID), the resolved `contextObjectId`, and your suggested `branchPurpose` + a one-line `reasoning`. The result comes back `proposed`: that is the system working. You do not bind — the operator confirms.
|
|
39
|
+
|
|
40
|
+
### The firewall — the one rule you never bend
|
|
41
|
+
|
|
42
|
+
`branchPurpose: "client-comms"` is **irreversible**. Once a channel is client-comms the backend refuses to reclassify it. So:
|
|
43
|
+
|
|
44
|
+
- **Only suggest `client-comms` when you are confident the channel is client-facing.** A `general`, `random`, or internal team channel must NEVER be proposed as client-comms — misfiling an internal room as client comms is exactly the mistake the firewall exists to prevent.
|
|
45
|
+
- **When the side is unclear, OMIT `branchPurpose`** and let the human choose on approval. An unbound bind with the purpose left open is fine; a wrong client-comms bind is not.
|
|
46
|
+
- You always PROPOSE. There is no path here where you silently set client-comms. The human owns that decision by approving.
|
|
47
|
+
|
|
48
|
+
Auto-binding on strong identity signals lives elsewhere; **from this skill you always propose.**
|
|
49
|
+
|
|
50
|
+
## Role-aware people guard (read this twice)
|
|
51
|
+
|
|
52
|
+
WHO is in the channel changes what a person IS. Get this wrong and you propose your own teammates as leads.
|
|
53
|
+
|
|
54
|
+
- **Internal channel** (`branchPurpose` = `team`): every human here is OUR teammate. Never propose a teammate as a client, lead, prospect, or contact. Surface what they DECIDED or COMMITTED to — not who they are.
|
|
55
|
+
- **Client channel** (`branchPurpose` = `client…`): the channel mixes client-side people with our own team who also post there. Separate the two. Only genuine client-side people become the client company's contacts; our teammates in the thread stay teammates and are never attached to the client.
|
|
56
|
+
|
|
57
|
+
When a person's side is unclear, ask or leave them out — do not guess a client relationship into existence.
|
|
58
|
+
|
|
59
|
+
## Output
|
|
60
|
+
|
|
61
|
+
Return a short, scannable digest: the few things worth attention, each with your advice or a status read ("decided X", "Y is waiting on you", "this deal moved to negotiating"). Lead with what matters most; skip the exhaustive recap.
|
|
62
|
+
|
|
63
|
+
Everything you propose goes through governance — you PROPOSE, you do not force. A `proposed` result is the system working, not a failure. If nothing crossed the bar, a one-line "nothing worth capturing from this window" is the correct and complete answer.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
## Document embeds — live entities/views/cells inside markdown
|
|
2
|
+
|
|
3
|
+
Documents (`type: "markdown"`) can embed **live, rendering** Synap objects inline, not
|
|
4
|
+
just links. The browser's markdown engine parses a small set of remark **container
|
|
5
|
+
directives** and swaps them for real components — an entity card, a view, or a cell
|
|
6
|
+
— wherever they appear in the prose.
|
|
7
|
+
|
|
8
|
+
**This is a DOCUMENTS-only mechanism.** It is unrelated to the `[[kind:id|label]]`
|
|
9
|
+
inline chips described in `inline-patterns.md` — those render **only** in Companion
|
|
10
|
+
chat replies. Never put a `:::synap-*` directive in a chat reply, and never put a
|
|
11
|
+
`[[…]]` chip in a document's `content`. Different surface, different grammar.
|
|
12
|
+
|
|
13
|
+
### Syntax
|
|
14
|
+
|
|
15
|
+
<!-- brief:start -->
|
|
16
|
+
|
|
17
|
+
A container directive: three colons, the directive name, `{attrs}` on the opening
|
|
18
|
+
line, three colons alone on the closing line.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
:::synap-entity{id="ent_abc123"}
|
|
22
|
+
:::
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
| Directive | Required attrs | Optional attrs | Renders |
|
|
26
|
+
| -------------- | --------------------------------------------- | -------------- | ------------------------------------------------- |
|
|
27
|
+
| `synap-entity` | `id` (entity UUID) | — | Compact entity card (`__entity-block` cell) |
|
|
28
|
+
| `synap-view` | `viewId` (view UUID) | — | Embedded, read-only view (`__embedded-view` cell) |
|
|
29
|
+
| `synap-cell` | `instanceId` **OR** (`cellKey` + `cellProps`) | — | A persisted cell instance, or an inline cell ref |
|
|
30
|
+
|
|
31
|
+
Only real IDs from prior tool results — never invent one. This is a
|
|
32
|
+
DOCUMENTS-only grammar: never use it in a chat reply, and never use a
|
|
33
|
+
`[[kind:id|label]]` chip inside a document's `content`.
|
|
34
|
+
|
|
35
|
+
<!-- brief:end -->
|
|
36
|
+
|
|
37
|
+
For `synap-cell`: an explicit `instanceId` always wins if present — it renders a
|
|
38
|
+
persisted cell instance from `/api/hub/cells`. Otherwise the pair `cellKey` +
|
|
39
|
+
`cellProps` builds an inline ref (`cellRefFromLegacy`). `cellProps` is a JSON string,
|
|
40
|
+
e.g. `cellProps='{"profileSlug":"task"}'`.
|
|
41
|
+
|
|
42
|
+
When you write a document's `content` directly (via `synap_create_document` /
|
|
43
|
+
`POST /api/hub/documents`), you're writing raw markdown text — quote `cellProps`'
|
|
44
|
+
JSON with single quotes (`cellProps='{"profileSlug":"task"}'`) so the inner `"`
|
|
45
|
+
characters don't collide with the directive's own `key="value"` quoting; the
|
|
46
|
+
markdown renderer (remark-directive) parses this directly, no escaping needed.
|
|
47
|
+
|
|
48
|
+
One caveat: if a human later opens the document in the rich-text editor, its
|
|
49
|
+
Tiptap round-trip serializer re-emits every directive as `key="value"` and
|
|
50
|
+
**drops any attribute value containing `"` or `}`** (it would otherwise corrupt
|
|
51
|
+
the directive) — so an inline `cellProps` blob can be silently lost on the next
|
|
52
|
+
editor save. For a cell you expect to survive editing, create it first
|
|
53
|
+
(`synap_create_cell` / `POST /api/hub/cells`) and embed it by `instanceId`
|
|
54
|
+
instead of inlining `cellProps`.
|
|
55
|
+
|
|
56
|
+
### Rules
|
|
57
|
+
|
|
58
|
+
- **Only real IDs from prior tool results.** Never invent an entity/view/instance
|
|
59
|
+
ID. Create or look it up first (`synap_create_entity`, `synap_get_entities`,
|
|
60
|
+
`synap_create_view`, `synap_create_cell`), then embed the ID you got back.
|
|
61
|
+
- **Embeds are for DOCUMENTS.** The `[[…]]` inline chips are for Companion chat
|
|
62
|
+
replies. Do not mix the two grammars across surfaces.
|
|
63
|
+
- **Embed vs. link:** embed when the reader benefits from seeing the live
|
|
64
|
+
object in place — a stat card inside a report, the linked meeting entity inside
|
|
65
|
+
meeting notes, a pipeline view inside a status update. Link (`entities WHERE
|
|
66
|
+
documentId = ?` attachment, or a plain reference to the ID) when you just need
|
|
67
|
+
traceability and the reader doesn't need to see it rendered inline — most
|
|
68
|
+
documents should still be _attached_ to one entity (see `writes.md`) regardless
|
|
69
|
+
of whether they also embed others inline.
|
|
70
|
+
- A directive with a missing/invalid required attribute renders a visible error
|
|
71
|
+
block in the browser (`Error: View ID is required` / `Error: Cell type is
|
|
72
|
+
required`) — always double-check the ID before writing the directive.
|
|
73
|
+
|
|
74
|
+
### Worked example 1 — meeting notes embedding the meeting entity
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
POST /api/hub/documents
|
|
78
|
+
{
|
|
79
|
+
"userId": "{userId}",
|
|
80
|
+
"workspaceId": "{workspaceId}",
|
|
81
|
+
"title": "Meeting notes — 2026-07-12",
|
|
82
|
+
"type": "markdown",
|
|
83
|
+
"entityId": "ent_event_kickoff",
|
|
84
|
+
"content": "# Kickoff meeting\n\n:::synap-entity{id=\"ent_event_kickoff\"}\n:::\n\n## Decisions\n- Ship the pilot by August 1\n\n## Action items\n- [ ] Draft the rollout plan"
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The event entity renders as a live card at the top of the notes — attendees,
|
|
89
|
+
time, status stay current even if the entity changes later.
|
|
90
|
+
|
|
91
|
+
### Worked example 2 — status report embedding a pipeline view
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
POST /api/hub/documents
|
|
95
|
+
{
|
|
96
|
+
"userId": "{userId}",
|
|
97
|
+
"workspaceId": "{workspaceId}",
|
|
98
|
+
"title": "Weekly deals update",
|
|
99
|
+
"type": "markdown",
|
|
100
|
+
"entityId": "ent_project_eve",
|
|
101
|
+
"content": "# Weekly update\n\nThree deals moved to negotiating this week.\n\n:::synap-view{viewId=\"view_deals_pipeline\"}\n:::\n\nSee the board above for the live state."
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Worked example 3 — report embedding an inline stat cell
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
POST /api/hub/documents
|
|
109
|
+
{
|
|
110
|
+
"userId": "{userId}",
|
|
111
|
+
"workspaceId": "{workspaceId}",
|
|
112
|
+
"title": "Q2 task summary",
|
|
113
|
+
"type": "markdown",
|
|
114
|
+
"entityId": "ent_project_eve",
|
|
115
|
+
"content": "# Q2 summary\n\n:::synap-cell{cellKey=\"stat-card\" cellProps='{\"profileSlug\":\"task\"}'}\n:::\n\nOpen tasks are trending down."
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Note the mixed quoting: the directive's own attribute values use double quotes
|
|
120
|
+
(`cellKey="stat-card"`), so the outer `cellProps` value uses single quotes to hold
|
|
121
|
+
its JSON — the JSON itself must not contain any `"` once flattened into the
|
|
122
|
+
attribute string, or the serializer will drop it. When in doubt, prefer a
|
|
123
|
+
persisted `instanceId` over inline `cellProps`.
|