@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
|
@@ -27,6 +27,8 @@ metadata:
|
|
|
27
27
|
|
|
28
28
|
You extend a user's Synap pod schema: new entity profiles, new properties on existing profiles, overlay properties scoped to one workspace. The core rule: **reuse before extending.** Creating duplicate profiles fractures the graph.
|
|
29
29
|
|
|
30
|
+
---
|
|
31
|
+
|
|
30
32
|
## Before you touch anything
|
|
31
33
|
|
|
32
34
|
Always inventory first. Never assume the schema is empty.
|
|
@@ -42,6 +44,61 @@ GET /api/hub/property-defs?userId={userId}&workspaceId={workspaceId}&profileId={
|
|
|
42
44
|
|
|
43
45
|
The `synap` skill's `scripts/orient.sh` already fetches profiles — reuse its output.
|
|
44
46
|
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Read before you write
|
|
50
|
+
|
|
51
|
+
Synap data is a typed graph — never write blind. Before creating or updating an
|
|
52
|
+
entity, work the loop the same way you'd read a file before editing it:
|
|
53
|
+
|
|
54
|
+
1. **MAP** — know what types exist: `list_profiles` (the cheap map of entity
|
|
55
|
+
profiles), `list_views` for views.
|
|
56
|
+
2. **SEARCH** — `search_unified({ query: <title>, collections: ["entities"] })`.
|
|
57
|
+
If a close match exists, LINK to it (relation or entity_id property) — do NOT
|
|
58
|
+
create a duplicate. Create only when there is genuinely no match.
|
|
59
|
+
3. **READ THE SCHEMA** — before writing to a profile you haven't inspected this
|
|
60
|
+
session, call `get_profile({ slug })` for its real property defs (exact keys,
|
|
61
|
+
value types, enum options, link targets). For views, read the config
|
|
62
|
+
(`get_bento_schema`) before `create_view`.
|
|
63
|
+
4. **WRITE INTO THE REAL FIELDS** — map each value to its correct typed property:
|
|
64
|
+
right `key`, valid `valueType` (dates as ISO, numbers as numbers), enum values
|
|
65
|
+
that satisfy the constraint, links via the property's `linksTo` target. Don't
|
|
66
|
+
invent property keys. A value with no matching property goes into
|
|
67
|
+
description/content, or propose a new one with `create_property_def` — never
|
|
68
|
+
drop it into a stray key.
|
|
69
|
+
5. **CONNECT** — every new entity links to at least one other. Duplicates and
|
|
70
|
+
orphans are the two ways the graph degrades; avoid both.
|
|
71
|
+
|
|
72
|
+
## Complete intent, governed outcome
|
|
73
|
+
|
|
74
|
+
`title` + `content` is only a minimum payload, not Synap's data model. Once
|
|
75
|
+
you have read the schema, send the complete intent that is known: `profileSlug`,
|
|
76
|
+
title, typed `properties`, short `description`, long-form `content`, an existing
|
|
77
|
+
`projectId`, links, and source/session provenance. Include role `facets` in the
|
|
78
|
+
same composite plan whenever they must be reviewed with the entity.
|
|
79
|
+
|
|
80
|
+
- **One entity with known fields and no creation-time role change** → use
|
|
81
|
+
`create_entity` / `POST /entities`.
|
|
82
|
+
- **Several entities, facets, or relations that belong in one review** → use the
|
|
83
|
+
composite graph/capture-plan door, never a loose sequence of creates.
|
|
84
|
+
- **Raw input whose structure is unknown** → use capture to produce a plan;
|
|
85
|
+
preserve an original file with `keepRaw` when supplied. Raw source is not the
|
|
86
|
+
same thing as an entity's edited content.
|
|
87
|
+
|
|
88
|
+
Workspace is an explicit lens: omit it to read the pod/base schema and let the
|
|
89
|
+
profile's placement rule apply. Pass a workspace only when the user or a
|
|
90
|
+
reviewed routing decision actually selected it; then its overlays are valid.
|
|
91
|
+
Never fill it from a configured/default workspace.
|
|
92
|
+
|
|
93
|
+
Read the write receipt before continuing. `pending` means a proposal exists and
|
|
94
|
+
no entity has materialized; `applied` means the reported operations completed;
|
|
95
|
+
`partial` means independent follow-up operations failed and must be repaired or
|
|
96
|
+
surfaced. Do not send a speculative second update merely because a write
|
|
97
|
+
completed — enrich only when you learned genuinely new information or the
|
|
98
|
+
receipt identifies a specific missing field.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
45
102
|
## Discover profiles — never assume
|
|
46
103
|
|
|
47
104
|
**Always call `GET /api/hub/profiles?workspaceId={workspaceId}` first.** Profiles are dynamic — every pod and workspace has a different set depending on what was seeded and what the user created. Never assume a profile slug exists without verifying.
|
|
@@ -67,21 +124,41 @@ Custom workspace templates (devplane, content, etc.) add their own profiles enti
|
|
|
67
124
|
|
|
68
125
|
Before creating a new profile: **does one of these already fit?** A podcast episode is arguably an `article`. A meeting is an `event`. A book to read is an `article` or `bookmark`. Err on the side of reuse + extension, not creation.
|
|
69
126
|
|
|
70
|
-
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## When to extend an existing profile vs. create a new one vs. attach a facet
|
|
130
|
+
|
|
131
|
+
There are three moves, not two. Before extending or creating, ask whether the thing is really a **role** the entity plays rather than a new kind of entity at all — that's a facet, and it's the move people skip.
|
|
132
|
+
|
|
133
|
+
**Kind + Facets, the rule:** one entity = one kind (`profiles.profileKind = 'kind'`). Roles the entity plays — client, partner, investor, prospect — are role-profiles (`profileKind = 'role'`, `applicableKinds[]`) attached via `entity_facets`: additive, workspace-lensed, NOT entities. A facet cascades with its parent entity; only promote a role to a full kind if it accrues its own independent life.
|
|
134
|
+
|
|
135
|
+
**The litmus test:**
|
|
136
|
+
|
|
137
|
+
- Both sides of a connection are independently-alive kinds → it's a **relation** (e.g. person "works at" company — two entities, linked).
|
|
138
|
+
- One side is just wearing a hat with no independent lifecycle → it's a **facet** (e.g. "client" on a company — attach the role, don't create a new entity).
|
|
139
|
+
- The connection itself accrues its own multi-entity lifecycle (stages, money, deadlines, outcomes) → it gets **promoted to its own kind**. `deal` is the precedent: a buyer × seller × stage relationship-thing has its own life (pipeline stage, amount, close date) independent of either party, so it's kept as a primary kind, never a facet.
|
|
140
|
+
|
|
141
|
+
Attach when:
|
|
142
|
+
|
|
143
|
+
- The thing is a role/hat the entity is wearing (client, partner, investor, prospect, sponsor) — it has no properties or lifecycle independent of the parent entity
|
|
144
|
+
- AI-driven creation: resolve identity FIRST (strong signals — email, phone, url) before creating anything; if the entity already exists, `attach_facet` the new role onto it — never spin up a second entity for a hat
|
|
71
145
|
|
|
72
146
|
Extend when:
|
|
73
147
|
|
|
74
|
-
- The thing fits an existing category (a
|
|
148
|
+
- The thing fits an existing category (a `client` **facet** is the role; if you instead need a distinct persisted sub-kind with its own fields, consider inheritance)
|
|
75
149
|
- The user needs 1–3 extra fields on an existing type
|
|
76
150
|
- The new fields are workspace-specific (use an overlay, see below)
|
|
77
151
|
|
|
78
152
|
Create new when:
|
|
79
153
|
|
|
80
|
-
- None of the system profiles fits
|
|
154
|
+
- None of the system profiles fits, and it's not a role of an existing entity
|
|
81
155
|
- The thing has a clearly distinct set of properties (10+ fields)
|
|
82
156
|
- The domain model genuinely calls for a new first-class type (recipe, workout, podcast episode, investment, plant, medication, vehicle, property listing…)
|
|
157
|
+
- It's a relationship-thing that accrues its own independent lifecycle (the `deal` precedent above)
|
|
83
158
|
|
|
84
|
-
Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ.
|
|
159
|
+
Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ. But if `client` is really just a role a `company` or `person` plays (no independent properties of its own), it shouldn't be a profile at all — it's a facet, attached via `attach_facet`, never a second entity.
|
|
160
|
+
|
|
161
|
+
---
|
|
85
162
|
|
|
86
163
|
## Creating a new profile
|
|
87
164
|
|
|
@@ -101,6 +178,8 @@ POST /api/hub/profiles
|
|
|
101
178
|
|
|
102
179
|
Then add properties one by one (see below). You do NOT declare properties inline on the profile — they're separate rows.
|
|
103
180
|
|
|
181
|
+
---
|
|
182
|
+
|
|
104
183
|
## Creating properties
|
|
105
184
|
|
|
106
185
|
```json
|
|
@@ -131,6 +210,8 @@ For linking properties, always use `entity_id` with `targetProfileSlug` in const
|
|
|
131
210
|
|
|
132
211
|
This enables auto-sync (see `../synap/linking.md`) — the property becomes a typed link that shows up in graph traversals automatically.
|
|
133
212
|
|
|
213
|
+
---
|
|
214
|
+
|
|
134
215
|
## Workspace overlay properties
|
|
135
216
|
|
|
136
217
|
New concept (2026-04-10+). A single profile (say `task`) can have **different fields in different workspaces** without copying the profile. Set `overlay: true` on `POST /property-defs`:
|
|
@@ -154,6 +235,8 @@ Use cases:
|
|
|
154
235
|
|
|
155
236
|
Overlays don't leak: workspace A can't see workspace B's overlay properties even though both share the profile. For the full scope model, read **`property-types.md`** §Overlay.
|
|
156
237
|
|
|
238
|
+
---
|
|
239
|
+
|
|
157
240
|
## Entity scope (pod-wide vs. workspace-scoped)
|
|
158
241
|
|
|
159
242
|
Profiles have an `entityScope` that determines where entities of that type live:
|
|
@@ -163,6 +246,8 @@ Profiles have an `entityScope` that determines where entities of that type live:
|
|
|
163
246
|
|
|
164
247
|
Defaults to `workspace` if not set on the profile. The user can toggle this per profile in ProfileEditor Settings. If you're creating a profile for something clearly pod-wide (a person, a podcast the user follows, a book in their library), set `entityScope: "pod"` explicitly.
|
|
165
248
|
|
|
249
|
+
---
|
|
250
|
+
|
|
166
251
|
## Custom relations
|
|
167
252
|
|
|
168
253
|
If the user wants a typed edge that isn't in the convention list (see `../synap/linking.md`), you can define it:
|
|
@@ -182,6 +267,8 @@ POST /api/hub/relation-defs
|
|
|
182
267
|
|
|
183
268
|
Defining a relation def is rarely worth it — `related_to` + a property usually suffices. Only create one when the relationship is semantic enough that UI should treat it specially (e.g., show "mentored by Jane" on a person's profile card).
|
|
184
269
|
|
|
270
|
+
---
|
|
271
|
+
|
|
185
272
|
## Worked example — "I want to track podcasts I listen to"
|
|
186
273
|
|
|
187
274
|
1. Inventory. `GET /profiles` → no `podcast` profile, no `podcast_episode`.
|
|
@@ -213,7 +300,9 @@ Defining a relation def is rarely worth it — `related_to` + a property usually
|
|
|
213
300
|
|
|
214
301
|
7. Tell the user. "I added `podcast` and `podcast_episode` to your pod with linking between them. You can create your first episode now, or want me to also add a view for it?" (Hand off to the `synap-ui` skill if they say yes.)
|
|
215
302
|
|
|
216
|
-
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Common mistakes — schema extension
|
|
217
306
|
|
|
218
307
|
1. **Creating a profile that already exists (e.g., `meeting` when `event` fits).** Always inventory first.
|
|
219
308
|
2. **Declaring properties inline on the profile object.** Properties are separate rows; use `POST /property-defs`.
|
|
@@ -223,7 +312,9 @@ Defining a relation def is rarely worth it — `related_to` + a property usually
|
|
|
223
312
|
6. **Creating an overlay when a base property is wanted.** Overlays only appear in one workspace. If the user wants the field everywhere, don't set `overlay: true`.
|
|
224
313
|
7. **Creating a custom profile when extension would work.** `client extends contact` is cleaner than a parallel `client` profile.
|
|
225
314
|
|
|
226
|
-
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## When you need more — schema extension
|
|
227
318
|
|
|
228
319
|
- Full `valueType` reference + constraints + uiHints → **`property-types.md`**
|
|
229
320
|
- Inheritance, overlay scope semantics, pod-wide caveats → **`property-types.md`** §Scope
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
profiles.md
|
|
2
|
+
before-you-touch.md
|
|
3
|
+
read-before-write.md
|
|
4
|
+
discover-profiles.md
|
|
5
|
+
extend-vs-create.md
|
|
6
|
+
creating-profiles.md
|
|
7
|
+
property-defs.md
|
|
8
|
+
overlay-properties.md
|
|
9
|
+
entity-scope.md
|
|
10
|
+
relations.md
|
|
11
|
+
worked-example.md
|
|
12
|
+
common-mistakes.md
|
|
13
|
+
more.md
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: synap-schema
|
|
2
|
+
description: >
|
|
3
|
+
Use this skill when the user needs to extend Synap's data model — defining a
|
|
4
|
+
new type of thing (entity profile) or adding/modifying fields (property defs)
|
|
5
|
+
on existing types. Triggers: "I need a new type for podcasts/recipes/workouts/
|
|
6
|
+
clients/books/plants/investments", "add a priority field to tasks", "create a
|
|
7
|
+
property for tracking budget", "I want to track Y and it's not in my current
|
|
8
|
+
schema", defining custom relations, setting up a profile for a specific domain
|
|
9
|
+
(real estate, music production, research, fitness, cooking). Also triggers on:
|
|
10
|
+
"do I already have a profile for X?", "what fields does <profile> have?",
|
|
11
|
+
extending an existing profile with workspace-specific overlay properties.
|
|
12
|
+
Do NOT use this skill for creating instances of existing types — the core
|
|
13
|
+
`synap` skill handles that. This skill changes the SCHEMA, not the data.
|
|
14
|
+
metadata:
|
|
15
|
+
openclaw:
|
|
16
|
+
requires:
|
|
17
|
+
env: [SYNAP_HUB_API_KEY, SYNAP_POD_URL]
|
|
18
|
+
primaryEnv: SYNAP_HUB_API_KEY
|
|
19
|
+
homepage: https://synap.live
|
|
20
|
+
capabilities: [schema, profiles, properties]
|
|
21
|
+
os: [macos, linux, windows]
|
|
22
|
+
userInvocable: false
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## Before you touch anything
|
|
2
|
+
|
|
3
|
+
Always inventory first. Never assume the schema is empty.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
GET /api/hub/profiles?userId={userId}&workspaceId={workspaceId}
|
|
7
|
+
→ [{ slug, displayName, entityScope, parentProfileSlug,
|
|
8
|
+
properties: [{ slug, valueType, constraints, uiHints, targetProfileSlug? }] }]
|
|
9
|
+
|
|
10
|
+
GET /api/hub/property-defs?userId={userId}&workspaceId={workspaceId}&profileId={profileId}
|
|
11
|
+
→ [{ slug, valueType, constraints, uiHints, workspaceId /* null=base, uuid=overlay */ }]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The `synap` skill's `scripts/orient.sh` already fetches profiles — reuse its output.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
## Common mistakes — schema extension
|
|
2
|
+
|
|
3
|
+
1. **Creating a profile that already exists (e.g., `meeting` when `event` fits).** Always inventory first.
|
|
4
|
+
2. **Declaring properties inline on the profile object.** Properties are separate rows; use `POST /property-defs`.
|
|
5
|
+
3. **Using `string` for what should be `entity_id`.** If the field refers to another entity (host of a podcast), use `entity_id` + `targetProfileSlug` — enables auto-sync and link UX.
|
|
6
|
+
4. **Using `array` of strings for tags.** Tags are a built-in concept; reuse the `tags` property on `note`/`project` instead of creating a parallel field.
|
|
7
|
+
5. **Forgetting `entityScope`.** Defaults to `workspace`. If the thing is pod-wide (people, books, podcasts), set it explicitly.
|
|
8
|
+
6. **Creating an overlay when a base property is wanted.** Overlays only appear in one workspace. If the user wants the field everywhere, don't set `overlay: true`.
|
|
9
|
+
7. **Creating a custom profile when extension would work.** `client extends contact` is cleaner than a parallel `client` profile.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Creating a new profile
|
|
2
|
+
|
|
3
|
+
```json
|
|
4
|
+
POST /api/hub/profiles
|
|
5
|
+
{
|
|
6
|
+
"userId": "{userId}",
|
|
7
|
+
"workspaceId": "{workspaceId}",
|
|
8
|
+
"slug": "podcast_episode", // snake_case, unique
|
|
9
|
+
"displayName": "Podcast Episode",
|
|
10
|
+
"description": "An episode of a podcast the user listens to",
|
|
11
|
+
"parentProfileId": "<id of article or null>", // optional, enables inheritance
|
|
12
|
+
"defaultValues": { "status": "queued" },
|
|
13
|
+
"uiHints": { "icon": "mic", "color": "purple" }
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then add properties one by one (see below). You do NOT declare properties inline on the profile — they're separate rows.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
## Discover profiles — never assume
|
|
2
|
+
|
|
3
|
+
**Always call `GET /api/hub/profiles?workspaceId={workspaceId}` first.** Profiles are dynamic — every pod and workspace has a different set depending on what was seeded and what the user created. Never assume a profile slug exists without verifying.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
GET /api/hub/profiles?workspaceId={workspaceId}
|
|
7
|
+
→ [{ slug, displayName, entityScope, parentSlug,
|
|
8
|
+
properties: [{ slug, valueType, required, ... }] }]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Read the response:
|
|
12
|
+
|
|
13
|
+
- `entityScope: "pod"` — visible across all workspaces
|
|
14
|
+
- `entityScope: "workspace"` — scoped to this workspace only (custom types, CRM profiles, template-seeded types)
|
|
15
|
+
- `parentSlug` — inheritance chain (e.g. `contact` extends `person`)
|
|
16
|
+
|
|
17
|
+
### Commonly seeded profiles (verify before using)
|
|
18
|
+
|
|
19
|
+
Standard pods typically include: `note`, `task`, `project`, `event`, `person`, `contact`, `company`, `bookmark`, `website`, `article`, `capture`, `file`, `anchor`, `decision`, `question`, `research`
|
|
20
|
+
|
|
21
|
+
CRM workspaces additionally have: `deal`, `client` — but **only** when a CRM workspace was created.
|
|
22
|
+
Custom workspace templates (devplane, content, etc.) add their own profiles entirely.
|
|
23
|
+
|
|
24
|
+
Before creating a new profile: **does one of these already fit?** A podcast episode is arguably an `article`. A meeting is an `event`. A book to read is an `article` or `bookmark`. Err on the side of reuse + extension, not creation.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## Entity scope (pod-wide vs. workspace-scoped)
|
|
2
|
+
|
|
3
|
+
Profiles have an `entityScope` that determines where entities of that type live:
|
|
4
|
+
|
|
5
|
+
- `entityScope: "pod"` — entities are pod-wide, visible in every workspace the user can access. Good for people, companies, notes, articles — things that cross contexts.
|
|
6
|
+
- `entityScope: "workspace"` — entities live in the workspace they were created in. Good for deals, files, workspace-specific artifacts.
|
|
7
|
+
|
|
8
|
+
Defaults to `workspace` if not set on the profile. The user can toggle this per profile in ProfileEditor Settings. If you're creating a profile for something clearly pod-wide (a person, a podcast the user follows, a book in their library), set `entityScope: "pod"` explicitly.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## When to extend an existing profile vs. create a new one vs. attach a facet
|
|
2
|
+
|
|
3
|
+
There are three moves, not two. Before extending or creating, ask whether the thing is really a **role** the entity plays rather than a new kind of entity at all — that's a facet, and it's the move people skip.
|
|
4
|
+
|
|
5
|
+
**Kind + Facets, the rule:** one entity = one kind (`profiles.profileKind = 'kind'`). Roles the entity plays — client, partner, investor, prospect — are role-profiles (`profileKind = 'role'`, `applicableKinds[]`) attached via `entity_facets`: additive, workspace-lensed, NOT entities. A facet cascades with its parent entity; only promote a role to a full kind if it accrues its own independent life.
|
|
6
|
+
|
|
7
|
+
**The litmus test:**
|
|
8
|
+
|
|
9
|
+
- Both sides of a connection are independently-alive kinds → it's a **relation** (e.g. person "works at" company — two entities, linked).
|
|
10
|
+
- One side is just wearing a hat with no independent lifecycle → it's a **facet** (e.g. "client" on a company — attach the role, don't create a new entity).
|
|
11
|
+
- The connection itself accrues its own multi-entity lifecycle (stages, money, deadlines, outcomes) → it gets **promoted to its own kind**. `deal` is the precedent: a buyer × seller × stage relationship-thing has its own life (pipeline stage, amount, close date) independent of either party, so it's kept as a primary kind, never a facet.
|
|
12
|
+
|
|
13
|
+
Attach when:
|
|
14
|
+
|
|
15
|
+
- The thing is a role/hat the entity is wearing (client, partner, investor, prospect, sponsor) — it has no properties or lifecycle independent of the parent entity
|
|
16
|
+
- AI-driven creation: resolve identity FIRST (strong signals — email, phone, url) before creating anything; if the entity already exists, `attach_facet` the new role onto it — never spin up a second entity for a hat
|
|
17
|
+
|
|
18
|
+
Extend when:
|
|
19
|
+
|
|
20
|
+
- The thing fits an existing category (a `client` **facet** is the role; if you instead need a distinct persisted sub-kind with its own fields, consider inheritance)
|
|
21
|
+
- The user needs 1–3 extra fields on an existing type
|
|
22
|
+
- The new fields are workspace-specific (use an overlay, see below)
|
|
23
|
+
|
|
24
|
+
Create new when:
|
|
25
|
+
|
|
26
|
+
- None of the system profiles fits, and it's not a role of an existing entity
|
|
27
|
+
- The thing has a clearly distinct set of properties (10+ fields)
|
|
28
|
+
- The domain model genuinely calls for a new first-class type (recipe, workout, podcast episode, investment, plant, medication, vehicle, property listing…)
|
|
29
|
+
- It's a relationship-thing that accrues its own independent lifecycle (the `deal` precedent above)
|
|
30
|
+
|
|
31
|
+
Prefer **inheritance** over new profiles when a system parent fits. `contact extends person` is the pattern — a new `client` profile can `parentProfileSlug: "contact"` and only add the fields that differ. But if `client` is really just a role a `company` or `person` plays (no independent properties of its own), it shouldn't be a profile at all — it's a facet, attached via `attach_facet`, never a second entity.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
## When you need more — schema extension
|
|
2
|
+
|
|
3
|
+
- Full `valueType` reference + constraints + uiHints → **`property-types.md`**
|
|
4
|
+
- Inheritance, overlay scope semantics, pod-wide caveats → **`property-types.md`** §Scope
|
|
5
|
+
- Creating views over the new profile → install the **`synap-ui`** skill
|
|
6
|
+
- Creating instances of the new profile → use the core **`synap`** skill
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
## Workspace overlay properties
|
|
2
|
+
|
|
3
|
+
New concept (2026-04-10+). A single profile (say `task`) can have **different fields in different workspaces** without copying the profile. Set `overlay: true` on `POST /property-defs`:
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
POST /api/hub/property-defs
|
|
7
|
+
{
|
|
8
|
+
"userId": "{userId}",
|
|
9
|
+
"workspaceId": "{workspaceId}",
|
|
10
|
+
"profileId": "{taskProfileId}",
|
|
11
|
+
"slug": "billableHours",
|
|
12
|
+
"valueType": "number",
|
|
13
|
+
"overlay": true // this property only appears in this workspace
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Use cases:
|
|
18
|
+
|
|
19
|
+
- "My consulting workspace needs `billableHours` on tasks; my personal workspace doesn't."
|
|
20
|
+
- "Our sales workspace wants a `dealSize` on contacts; engineering doesn't."
|
|
21
|
+
|
|
22
|
+
Overlays don't leak: workspace A can't see workspace B's overlay properties even though both share the profile. For the full scope model, read **`property-types.md`** §Overlay.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
## Creating properties
|
|
2
|
+
|
|
3
|
+
```json
|
|
4
|
+
POST /api/hub/property-defs
|
|
5
|
+
{
|
|
6
|
+
"userId": "{userId}",
|
|
7
|
+
"workspaceId": "{workspaceId}",
|
|
8
|
+
"profileId": "{profileId}", // the profile this property belongs to
|
|
9
|
+
"slug": "durationMinutes",
|
|
10
|
+
"valueType": "number",
|
|
11
|
+
"constraints": { "min": 0, "max": 600 },
|
|
12
|
+
"uiHints": { "format": "compact", "displayName": "Duration" }
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Value types: `string`, `number`, `boolean`, `date`, `entity_id`, `array`, `object`, `secret`. Full reference in **`property-types.md`**.
|
|
17
|
+
|
|
18
|
+
For linking properties, always use `entity_id` with `targetProfileSlug` in constraints:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"slug": "hostId",
|
|
23
|
+
"valueType": "entity_id",
|
|
24
|
+
"constraints": { "targetProfileSlug": "person" },
|
|
25
|
+
"uiHints": { "displayName": "Host" }
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This enables auto-sync (see `../synap/linking.md`) — the property becomes a typed link that shows up in graph traversals automatically.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
## Read before you write
|
|
2
|
+
|
|
3
|
+
Synap data is a typed graph — never write blind. Before creating or updating an
|
|
4
|
+
entity, work the loop the same way you'd read a file before editing it:
|
|
5
|
+
|
|
6
|
+
1. **MAP** — know what types exist: `list_profiles` (the cheap map of entity
|
|
7
|
+
profiles), `list_views` for views.
|
|
8
|
+
2. **SEARCH** — `search_unified({ query: <title>, collections: ["entities"] })`.
|
|
9
|
+
If a close match exists, LINK to it (relation or entity_id property) — do NOT
|
|
10
|
+
create a duplicate. Create only when there is genuinely no match.
|
|
11
|
+
3. **READ THE SCHEMA** — before writing to a profile you haven't inspected this
|
|
12
|
+
session, call `get_profile({ slug })` for its real property defs (exact keys,
|
|
13
|
+
value types, enum options, link targets). For views, read the config
|
|
14
|
+
(`get_bento_schema`) before `create_view`.
|
|
15
|
+
4. **WRITE INTO THE REAL FIELDS** — map each value to its correct typed property:
|
|
16
|
+
right `key`, valid `valueType` (dates as ISO, numbers as numbers), enum values
|
|
17
|
+
that satisfy the constraint, links via the property's `linksTo` target. Don't
|
|
18
|
+
invent property keys. A value with no matching property goes into
|
|
19
|
+
description/content, or propose a new one with `create_property_def` — never
|
|
20
|
+
drop it into a stray key.
|
|
21
|
+
5. **CONNECT** — every new entity links to at least one other. Duplicates and
|
|
22
|
+
orphans are the two ways the graph degrades; avoid both.
|
|
23
|
+
|
|
24
|
+
## Complete intent, governed outcome
|
|
25
|
+
|
|
26
|
+
`title` + `content` is only a minimum payload, not Synap's data model. Once
|
|
27
|
+
you have read the schema, send the complete intent that is known: `profileSlug`,
|
|
28
|
+
title, typed `properties`, short `description`, long-form `content`, an existing
|
|
29
|
+
`projectId`, links, and source/session provenance. Include role `facets` in the
|
|
30
|
+
same composite plan whenever they must be reviewed with the entity.
|
|
31
|
+
|
|
32
|
+
- **One entity with known fields and no creation-time role change** → use
|
|
33
|
+
`create_entity` / `POST /entities`.
|
|
34
|
+
- **Several entities, facets, or relations that belong in one review** → use the
|
|
35
|
+
composite graph/capture-plan door, never a loose sequence of creates.
|
|
36
|
+
- **Raw input whose structure is unknown** → use capture to produce a plan;
|
|
37
|
+
preserve an original file with `keepRaw` when supplied. Raw source is not the
|
|
38
|
+
same thing as an entity's edited content.
|
|
39
|
+
|
|
40
|
+
Workspace is an explicit lens: omit it to read the pod/base schema and let the
|
|
41
|
+
profile's placement rule apply. Pass a workspace only when the user or a
|
|
42
|
+
reviewed routing decision actually selected it; then its overlays are valid.
|
|
43
|
+
Never fill it from a configured/default workspace.
|
|
44
|
+
|
|
45
|
+
Read the write receipt before continuing. `pending` means a proposal exists and
|
|
46
|
+
no entity has materialized; `applied` means the reported operations completed;
|
|
47
|
+
`partial` means independent follow-up operations failed and must be repaired or
|
|
48
|
+
surfaced. Do not send a speculative second update merely because a write
|
|
49
|
+
completed — enrich only when you learned genuinely new information or the
|
|
50
|
+
receipt identifies a specific missing field.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Custom relations
|
|
2
|
+
|
|
3
|
+
If the user wants a typed edge that isn't in the convention list (see `../synap/linking.md`), you can define it:
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
POST /api/hub/relation-defs
|
|
7
|
+
{
|
|
8
|
+
"userId": "{userId}",
|
|
9
|
+
"workspaceId": "{workspaceId}",
|
|
10
|
+
"slug": "mentored_by",
|
|
11
|
+
"displayName": "Mentored by",
|
|
12
|
+
"sourceProfileSlug": "person",
|
|
13
|
+
"targetProfileSlug": "person",
|
|
14
|
+
"bidirectional": false
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Defining a relation def is rarely worth it — `related_to` + a property usually suffices. Only create one when the relationship is semantic enough that UI should treat it specially (e.g., show "mentored by Jane" on a person's profile card).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Worked example — "I want to track podcasts I listen to"
|
|
2
|
+
|
|
3
|
+
1. Inventory. `GET /profiles` → no `podcast` profile, no `podcast_episode`.
|
|
4
|
+
2. Decide scope. Podcasts/episodes are pod-wide (same podcast across workspaces).
|
|
5
|
+
3. Create two profiles (podcast + episode) or one (episode only, with the show as a string property)? Decide based on the user's intent. If they want to group episodes by show → two profiles. If one-level is enough → one.
|
|
6
|
+
4. For two profiles:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
POST /profiles { slug: "podcast", displayName: "Podcast", entityScope: "pod", uiHints: { icon: "radio" } }
|
|
10
|
+
POST /profiles { slug: "podcast_episode", displayName: "Podcast Episode", parentProfileId: <articleId>, entityScope: "pod" }
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
5. Add properties on `podcast`:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
POST /property-defs { slug: "host", valueType: "string" }
|
|
17
|
+
POST /property-defs { slug: "rssUrl", valueType: "string", uiHints: { inputType: "url" } }
|
|
18
|
+
POST /property-defs { slug: "category", valueType: "string" }
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
6. Add properties on `podcast_episode`:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
POST /property-defs { slug: "podcastId", valueType: "entity_id", constraints: { targetProfileSlug: "podcast" } }
|
|
25
|
+
POST /property-defs { slug: "durationMinutes", valueType: "number" }
|
|
26
|
+
POST /property-defs { slug: "listenedAt", valueType: "date" }
|
|
27
|
+
POST /property-defs { slug: "rating", valueType: "number", constraints: { min: 1, max: 5 } }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
7. Tell the user. "I added `podcast` and `podcast_episode` to your pod with linking between them. You can create your first episode now, or want me to also add a view for it?" (Hand off to the `synap-ui` skill if they say yes.)
|
package/skills/synap-ui/SKILL.md
CHANGED
|
@@ -28,6 +28,8 @@ metadata:
|
|
|
28
28
|
|
|
29
29
|
You build the surfaces the user sees: views over their data, bento dashboards, full workspaces tuned for a domain. The core rule: **emergent complexity.** A workspace is a lens; a view is a lens; a bento is a composition of lenses. Everything renders through the cell system, nothing is hardcoded.
|
|
30
30
|
|
|
31
|
+
---
|
|
32
|
+
|
|
31
33
|
## Before you build anything
|
|
32
34
|
|
|
33
35
|
Always inventory. Never hallucinate view types, widget kinds, or profiles.
|
|
@@ -49,6 +51,8 @@ GET /api/hub/views?userId={userId}&workspaceId={workspaceId}
|
|
|
49
51
|
|
|
50
52
|
Widget definitions are the source of truth for which cells are installed and how to configure them. **Never guess cell kinds.** If a cell doesn't appear in the registry, don't reference it (unless it's a browser-native cell from the manifest).
|
|
51
53
|
|
|
54
|
+
---
|
|
55
|
+
|
|
52
56
|
## Four things you can build
|
|
53
57
|
|
|
54
58
|
1. **Views** — named queries + rendering config over entities of a given profile. Kanban of tasks, gallery of articles, calendar of events.
|
|
@@ -74,6 +78,8 @@ Widget definitions are the source of truth for which cells are installed and how
|
|
|
74
78
|
- Always `GET /api/hub/widget-definitions` first — if a cell already covers the need, use it. New cell definitions are permanent; only create when genuinely novel.
|
|
75
79
|
- For the full in-frame query/mutate/shell-actions API see the `synap` skill's **ViewFrame Cells** section (or load `synap-ui:SKILL` via `GET /api/hub/skills/system?sections=synap-ui:SKILL`).
|
|
76
80
|
|
|
81
|
+
---
|
|
82
|
+
|
|
77
83
|
## View types (16 total, 12 implemented)
|
|
78
84
|
|
|
79
85
|
Pick one that matches the data's shape AND the user's intent:
|
|
@@ -99,6 +105,8 @@ Pick one that matches the data's shape AND the user's intent:
|
|
|
99
105
|
|
|
100
106
|
Decision: the data has statuses → `kanban`. Dates → `calendar`. Many columns → `table`. Mixed types → `masonry` or `bento`. Full reference in **`view-types.md`**.
|
|
101
107
|
|
|
108
|
+
---
|
|
109
|
+
|
|
102
110
|
## Creating a view
|
|
103
111
|
|
|
104
112
|
```json
|
|
@@ -126,6 +134,8 @@ POST /api/hub/views
|
|
|
126
134
|
|
|
127
135
|
The `config` shape varies by view type — kanban needs `groupBy`, calendar needs a date property, gallery needs an image property. When in doubt, fetch an existing view of the same type first and mirror its structure.
|
|
128
136
|
|
|
137
|
+
---
|
|
138
|
+
|
|
129
139
|
## Bento layouts
|
|
130
140
|
|
|
131
141
|
A bento is a 12-column react-grid-layout. Blocks reference **cells** by kind.
|
|
@@ -162,6 +172,8 @@ Block kinds:
|
|
|
162
172
|
|
|
163
173
|
Full widget catalog in **`widget-catalog.md`**. Layout patterns in **`bento-recipes.md`**.
|
|
164
174
|
|
|
175
|
+
---
|
|
176
|
+
|
|
165
177
|
## Creating or proposing a workspace
|
|
166
178
|
|
|
167
179
|
**Always ask before creating.** Workspaces are big objects with profiles, views, members, bento, and seed data. Commit only after user confirms.
|
|
@@ -210,6 +222,8 @@ The canonical flow:
|
|
|
210
222
|
|
|
211
223
|
4. **On no**, don't commit. Offer to adjust.
|
|
212
224
|
|
|
225
|
+
---
|
|
226
|
+
|
|
213
227
|
## Proposing vs. extending
|
|
214
228
|
|
|
215
229
|
Before proposing a new workspace, ask: does one of the user's existing workspaces fit? A "Content" workspace and a "Writing" workspace are the same lens. Adding a view to the existing workspace is almost always better than creating a new one.
|
|
@@ -222,6 +236,8 @@ Create new when:
|
|
|
222
236
|
|
|
223
237
|
Otherwise: add a view, add a bento block, add properties — don't multiply workspaces.
|
|
224
238
|
|
|
239
|
+
---
|
|
240
|
+
|
|
225
241
|
## Worked example — "Make me a CRM"
|
|
226
242
|
|
|
227
243
|
1. Inventory. User already has `person`, `contact`, `company`, `deal`, `event` profiles (all system).
|
|
@@ -241,6 +257,8 @@ Otherwise: add a view, add a bento block, add properties — don't multiply work
|
|
|
241
257
|
4. Show to user. Confirm.
|
|
242
258
|
5. Commit via `POST /workspaces`.
|
|
243
259
|
|
|
260
|
+
---
|
|
261
|
+
|
|
244
262
|
## Arranging a bento after creation
|
|
245
263
|
|
|
246
264
|
```json
|
|
@@ -250,7 +268,9 @@ POST /api/hub/views/{bentoViewId}/arrange
|
|
|
250
268
|
|
|
251
269
|
`bento.arrange` is auto-approved by default. Safe to run without hesitation when the user rearranges or adds widgets.
|
|
252
270
|
|
|
253
|
-
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Common mistakes — UI generation
|
|
254
274
|
|
|
255
275
|
1. **Creating a workspace without asking.** Always propose + confirm. Workspaces are too big to auto-commit.
|
|
256
276
|
2. **Guessing widget kinds.** Always `GET /widget-definitions` first. A `kind` that isn't in the registry won't render.
|
|
@@ -261,6 +281,8 @@ POST /api/hub/views/{bentoViewId}/arrange
|
|
|
261
281
|
7. **Hardcoding config for view types you haven't checked.** Each view type's `config` shape is different. Get an example from `/views` first.
|
|
262
282
|
8. **Forgetting entityScope implications.** A view on a pod-scope profile (`note`) will show entities from every workspace the user can access — filter appropriately if you want workspace-local results.
|
|
263
283
|
|
|
284
|
+
---
|
|
285
|
+
|
|
264
286
|
## AI Companion integration
|
|
265
287
|
|
|
266
288
|
When you create views or entities for the user inside the AI Companion, **always emit inline pattern chips** at the end of your reply so the user can jump directly to what you built.
|
|
@@ -289,7 +311,9 @@ These cell keys are registered in the browser app but may not appear in `GET /ap
|
|
|
289
311
|
|
|
290
312
|
**Rule:** If a cell key is not in `GET /api/hub/widget-definitions`, do NOT reference it in bento config unless it is one of the four browser-native keys above. Unknown keys will silently fail to render.
|
|
291
313
|
|
|
292
|
-
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## When you need more — UI generation
|
|
293
317
|
|
|
294
318
|
- Full per-view-type `config` shapes → **`view-types.md`**
|
|
295
319
|
- Complete widget/cell catalog + configSchemas → **`widget-catalog.md`**
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: synap-ui
|
|
2
|
+
description: >
|
|
3
|
+
Use this skill when the user wants to BUILD interface in Synap — creating views,
|
|
4
|
+
dashboards, bento layouts, or whole workspaces over their data. Triggers:
|
|
5
|
+
"build me a dashboard for tracking X", "create a kanban for my projects",
|
|
6
|
+
"make a CRM workspace", "I want a feed view of my articles", "design a home
|
|
7
|
+
dashboard", "show my reading list as a gallery", "turn this into a
|
|
8
|
+
timeline/calendar/matrix", "generate a workspace for content creation /
|
|
9
|
+
sales / research / project management / fitness tracking", "arrange widgets
|
|
10
|
+
on my bento", "create a command / automation trigger". This skill PRESENTS
|
|
11
|
+
data — the underlying entities must already exist (use core `synap`) and
|
|
12
|
+
schema extensions happen via `synap-schema`. Always propose workspace creation
|
|
13
|
+
to the user before committing — workspaces are lenses on data, not silos,
|
|
14
|
+
and the user decides when a new lens is warranted.
|
|
15
|
+
metadata:
|
|
16
|
+
openclaw:
|
|
17
|
+
requires:
|
|
18
|
+
env: [SYNAP_HUB_API_KEY, SYNAP_POD_URL]
|
|
19
|
+
primaryEnv: SYNAP_HUB_API_KEY
|
|
20
|
+
homepage: https://synap.live
|
|
21
|
+
capabilities: [views, bento, workspaces, widgets]
|
|
22
|
+
os: [macos, linux, windows]
|
|
23
|
+
userInvocable: false
|