@synap-core/cli 1.12.2 → 1.13.1-next.20261102.ec3d166
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/LICENSE +21 -0
- package/README.md +38 -11
- package/dist/build-info.json +2 -3
- package/dist/commands/agents.d.ts +0 -1
- package/dist/commands/agents.js +13 -3
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.js +2 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/automation.js +46 -41
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/box.d.ts +42 -0
- package/dist/commands/box.js +89 -0
- package/dist/commands/box.js.map +1 -0
- package/dist/commands/bridge-setup.js +3 -1
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/capability.d.ts +87 -1
- package/dist/commands/capability.js +174 -64
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/close-questions.d.ts +27 -0
- package/dist/commands/close-questions.js +49 -0
- package/dist/commands/close-questions.js.map +1 -0
- package/dist/commands/close-questions.test.d.ts +1 -0
- package/dist/commands/close-questions.test.js +52 -0
- package/dist/commands/close-questions.test.js.map +1 -0
- package/dist/commands/connect.d.ts +1 -3
- package/dist/commands/connect.js +2 -2
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +72 -43
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +13 -0
- package/dist/commands/data-extra.js +35 -6
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.js +2 -1
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/doctor.d.ts +39 -0
- package/dist/commands/doctor.js +136 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/hooks.d.ts +19 -0
- package/dist/commands/hooks.js +70 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/import.d.ts +25 -0
- package/dist/commands/import.js +98 -12
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.js +63 -21
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys-request.d.ts +48 -0
- package/dist/commands/keys-request.js +236 -0
- package/dist/commands/keys-request.js.map +1 -0
- package/dist/commands/keys-request.test.d.ts +1 -0
- package/dist/commands/keys-request.test.js +176 -0
- package/dist/commands/keys-request.test.js.map +1 -0
- package/dist/commands/knowledge.d.ts +6 -0
- package/dist/commands/knowledge.js +13 -3
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/lens.js +2 -1
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.js +1 -1
- package/dist/commands/market-authoring.js.map +1 -1
- package/dist/commands/market.d.ts +61 -4
- package/dist/commands/market.js +106 -48
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +1 -1
- package/dist/commands/mcp.js +14 -9
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/observe.category.test.d.ts +1 -0
- package/dist/commands/observe.category.test.js +59 -0
- package/dist/commands/observe.category.test.js.map +1 -0
- package/dist/commands/observe.d.ts +3 -0
- package/dist/commands/observe.js +7 -5
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/observe.title.test.d.ts +1 -0
- package/dist/commands/observe.title.test.js +37 -0
- package/dist/commands/observe.title.test.js.map +1 -0
- package/dist/commands/playbook.js +9 -0
- package/dist/commands/playbook.js.map +1 -1
- package/dist/commands/pods.d.ts +6 -1
- package/dist/commands/pods.js +38 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +7 -1
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/proton-setup.js +3 -1
- package/dist/commands/proton-setup.js.map +1 -1
- package/dist/commands/providers.d.ts +22 -6
- package/dist/commands/providers.js +39 -32
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +36 -10
- package/dist/commands/raycast.js.map +1 -1
- package/dist/commands/session-feed-wait.d.ts +48 -0
- package/dist/commands/session-feed-wait.js +261 -0
- package/dist/commands/session-feed-wait.js.map +1 -0
- package/dist/commands/session-post.d.ts +40 -0
- package/dist/commands/session-post.js +96 -0
- package/dist/commands/session-post.js.map +1 -0
- package/dist/commands/session-wait.d.ts +9 -4
- package/dist/commands/session-wait.js +20 -5
- package/dist/commands/session-wait.js.map +1 -1
- package/dist/commands/sessions.d.ts +2 -0
- package/dist/commands/sessions.js +23 -0
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skills-commands.d.ts +2 -0
- package/dist/commands/skills-commands.js +9 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills-commands.test.d.ts +1 -0
- package/dist/commands/skills-commands.test.js +57 -0
- package/dist/commands/skills-commands.test.js.map +1 -0
- package/dist/commands/status.js +13 -7
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.backoff.test.js +13 -3
- package/dist/commands/statusline.backoff.test.js.map +1 -1
- package/dist/commands/statusline.d.ts +104 -9
- package/dist/commands/statusline.js +392 -148
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/statusline.line2.test.d.ts +15 -0
- package/dist/commands/statusline.line2.test.js +226 -0
- package/dist/commands/statusline.line2.test.js.map +1 -0
- package/dist/commands/statusline.needs-you.test.d.ts +1 -0
- package/dist/commands/statusline.needs-you.test.js +17 -0
- package/dist/commands/statusline.needs-you.test.js.map +1 -0
- package/dist/commands/statusline.now.test.d.ts +10 -0
- package/dist/commands/statusline.now.test.js +250 -0
- package/dist/commands/statusline.now.test.js.map +1 -0
- package/dist/commands/tracks.d.ts +68 -6
- package/dist/commands/tracks.js +272 -16
- package/dist/commands/tracks.js.map +1 -1
- package/dist/commands/upload.js +12 -0
- package/dist/commands/upload.js.map +1 -1
- package/dist/commands/wait.d.ts +124 -0
- package/dist/commands/wait.js +384 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/commands/wait.test.d.ts +8 -0
- package/dist/commands/wait.test.js +308 -0
- package/dist/commands/wait.test.js.map +1 -0
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.js +17 -0
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker-accounts.d.ts +149 -0
- package/dist/commands/worker-accounts.js +339 -0
- package/dist/commands/worker-accounts.js.map +1 -0
- package/dist/commands/worker-accounts.test.d.ts +1 -0
- package/dist/commands/worker-accounts.test.js +224 -0
- package/dist/commands/worker-accounts.test.js.map +1 -0
- package/dist/commands/worker-github-app.d.ts +63 -0
- package/dist/commands/worker-github-app.js +161 -0
- package/dist/commands/worker-github-app.js.map +1 -0
- package/dist/commands/worker-github-app.test.d.ts +1 -0
- package/dist/commands/worker-github-app.test.js +102 -0
- package/dist/commands/worker-github-app.test.js.map +1 -0
- package/dist/commands/worker-github-broker.d.ts +39 -0
- package/dist/commands/worker-github-broker.js +106 -0
- package/dist/commands/worker-github-broker.js.map +1 -0
- package/dist/commands/worker-github-broker.test.d.ts +1 -0
- package/dist/commands/worker-github-broker.test.js +90 -0
- package/dist/commands/worker-github-broker.test.js.map +1 -0
- package/dist/commands/worker-runs.test.d.ts +1 -0
- package/dist/commands/worker-runs.test.js +150 -0
- package/dist/commands/worker-runs.test.js.map +1 -0
- package/dist/commands/worker-worktrees.d.ts +34 -0
- package/dist/commands/worker-worktrees.js +87 -0
- package/dist/commands/worker-worktrees.js.map +1 -0
- package/dist/commands/worker.d.ts +406 -10
- package/dist/commands/worker.js +1180 -126
- package/dist/commands/worker.js.map +1 -1
- package/dist/commands/worker.test.js +588 -11
- package/dist/commands/worker.test.js.map +1 -1
- package/dist/index.js +220 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-door.d.ts +1 -3
- package/dist/lib/agent-door.js +10 -7
- package/dist/lib/agent-door.js.map +1 -1
- package/dist/lib/agents-config.d.ts +9 -0
- package/dist/lib/agents-config.js +20 -0
- package/dist/lib/agents-config.js.map +1 -1
- package/dist/lib/atomic-file.d.ts +20 -1
- package/dist/lib/atomic-file.js +100 -2
- package/dist/lib/atomic-file.js.map +1 -1
- package/dist/lib/auth.d.ts +28 -2
- package/dist/lib/auth.js +52 -12
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/box/egress.d.ts +82 -0
- package/dist/lib/box/egress.js +264 -0
- package/dist/lib/box/egress.js.map +1 -0
- package/dist/lib/box/evidence.d.ts +86 -0
- package/dist/lib/box/evidence.js +121 -0
- package/dist/lib/box/evidence.js.map +1 -0
- package/dist/lib/box/job-server.d.ts +72 -0
- package/dist/lib/box/job-server.js +250 -0
- package/dist/lib/box/job-server.js.map +1 -0
- package/dist/lib/box/provisioner.d.ts +83 -0
- package/dist/lib/box/provisioner.js +312 -0
- package/dist/lib/box/provisioner.js.map +1 -0
- package/dist/lib/box/proxmox.d.ts +112 -0
- package/dist/lib/box/proxmox.js +211 -0
- package/dist/lib/box/proxmox.js.map +1 -0
- package/dist/lib/box/wire.d.ts +98 -0
- package/dist/lib/box/wire.js +70 -0
- package/dist/lib/box/wire.js.map +1 -0
- package/dist/lib/bridge-invocation.test.d.ts +1 -0
- package/dist/lib/bridge-invocation.test.js +75 -0
- package/dist/lib/bridge-invocation.test.js.map +1 -0
- package/dist/lib/bridge-status.d.ts +144 -0
- package/dist/lib/bridge-status.js +227 -0
- package/dist/lib/bridge-status.js.map +1 -0
- package/dist/lib/bridge-status.test.d.ts +6 -0
- package/dist/lib/bridge-status.test.js +197 -0
- package/dist/lib/bridge-status.test.js.map +1 -0
- package/dist/lib/client-header.test.d.ts +1 -0
- package/dist/lib/client-header.test.js +103 -0
- package/dist/lib/client-header.test.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +89 -9
- package/dist/lib/conversation-headers.js +156 -3
- package/dist/lib/conversation-headers.js.map +1 -1
- package/dist/lib/conversation-headers.test.d.ts +1 -0
- package/dist/lib/conversation-headers.test.js +78 -0
- package/dist/lib/conversation-headers.test.js.map +1 -0
- package/dist/lib/credential-class.d.ts +40 -2
- package/dist/lib/credential-class.js +48 -6
- package/dist/lib/credential-class.js.map +1 -1
- package/dist/lib/device-connect.d.ts +45 -0
- package/dist/lib/device-connect.js +60 -0
- package/dist/lib/device-connect.js.map +1 -1
- package/dist/lib/exporter-coverage.d.ts +1 -1
- package/dist/lib/exporter-coverage.js +1 -1
- package/dist/lib/goal-words.d.ts +38 -0
- package/dist/lib/goal-words.js +115 -0
- package/dist/lib/goal-words.js.map +1 -0
- package/dist/lib/hub-client.d.ts +87 -8
- package/dist/lib/hub-client.js +205 -70
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/init-handoff.d.ts +8 -0
- package/dist/lib/init-handoff.js +9 -2
- package/dist/lib/init-handoff.js.map +1 -1
- package/dist/lib/key-locations.d.ts +3 -3
- package/dist/lib/key-locations.js +3 -39
- package/dist/lib/key-locations.js.map +1 -1
- package/dist/lib/key-source.d.ts +3 -1
- package/dist/lib/key-source.js +7 -4
- package/dist/lib/key-source.js.map +1 -1
- package/dist/lib/knowledge-title.d.ts +3 -2
- package/dist/lib/knowledge-title.js +3 -2
- package/dist/lib/knowledge-title.js.map +1 -1
- package/dist/lib/machine-instance.d.ts +7 -5
- package/dist/lib/machine-instance.js +7 -5
- package/dist/lib/machine-instance.js.map +1 -1
- package/dist/lib/mcp-bridge.d.ts +50 -0
- package/dist/lib/mcp-bridge.js +232 -11
- package/dist/lib/mcp-bridge.js.map +1 -1
- package/dist/lib/mcp-bridge.test.js +224 -4
- package/dist/lib/mcp-bridge.test.js.map +1 -1
- package/dist/lib/mcp-call.d.ts +5 -1
- package/dist/lib/mcp-call.js +7 -6
- package/dist/lib/mcp-call.js.map +1 -1
- package/dist/lib/mcp-connector-url.test.d.ts +1 -0
- package/dist/lib/mcp-connector-url.test.js +13 -0
- package/dist/lib/mcp-connector-url.test.js.map +1 -0
- package/dist/lib/mcp-snippets.d.ts +16 -0
- package/dist/lib/mcp-snippets.js +20 -2
- package/dist/lib/mcp-snippets.js.map +1 -1
- package/dist/lib/now-line.d.ts +66 -0
- package/dist/lib/now-line.js +193 -0
- package/dist/lib/now-line.js.map +1 -0
- package/dist/lib/now-line.test.d.ts +5 -0
- package/dist/lib/now-line.test.js +177 -0
- package/dist/lib/now-line.test.js.map +1 -0
- package/dist/lib/package-updates.d.ts +66 -0
- package/dist/lib/package-updates.js +76 -0
- package/dist/lib/package-updates.js.map +1 -0
- package/dist/lib/pod-moved.d.ts +70 -0
- package/dist/lib/pod-moved.js +146 -0
- package/dist/lib/pod-moved.js.map +1 -0
- package/dist/lib/pod-reach.d.ts +39 -0
- package/dist/lib/pod-reach.js +117 -0
- package/dist/lib/pod-reach.js.map +1 -0
- package/dist/lib/pod-reach.test.d.ts +1 -0
- package/dist/lib/pod-reach.test.js +67 -0
- package/dist/lib/pod-reach.test.js.map +1 -0
- package/dist/lib/pod.d.ts +8 -4
- package/dist/lib/pod.js +12 -10
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
- package/dist/lib/register-claude-code-mcp.test.js +97 -0
- package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
- package/dist/lib/review-credential.js +3 -1
- package/dist/lib/review-credential.js.map +1 -1
- package/dist/lib/safe-open.d.ts +5 -3
- package/dist/lib/safe-open.js +9 -8
- package/dist/lib/safe-open.js.map +1 -1
- package/dist/lib/self-host.d.ts +17 -0
- package/dist/lib/self-host.js +24 -0
- package/dist/lib/self-host.js.map +1 -0
- package/dist/lib/session-feed.d.ts +185 -0
- package/dist/lib/session-feed.js +257 -0
- package/dist/lib/session-feed.js.map +1 -0
- package/dist/lib/targets.d.ts +52 -3
- package/dist/lib/targets.js +150 -209
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/term.d.ts +24 -0
- package/dist/lib/term.js +52 -0
- package/dist/lib/term.js.map +1 -0
- package/dist/lib/term.test.d.ts +1 -0
- package/dist/lib/term.test.js +29 -0
- package/dist/lib/term.test.js.map +1 -0
- package/dist/lib/transcript-index.d.ts +94 -0
- package/dist/lib/transcript-index.js +321 -0
- package/dist/lib/transcript-index.js.map +1 -0
- package/dist/lib/transcript-index.test.d.ts +10 -0
- package/dist/lib/transcript-index.test.js +200 -0
- package/dist/lib/transcript-index.test.js.map +1 -0
- package/dist/lib/wait-help.d.ts +11 -0
- package/dist/lib/wait-help.js +25 -0
- package/dist/lib/wait-help.js.map +1 -0
- package/dist/lib/wait-state.d.ts +57 -0
- package/dist/lib/wait-state.js +114 -0
- package/dist/lib/wait-state.js.map +1 -0
- package/dist/lib/wake-hook-settings.d.ts +57 -0
- package/dist/lib/wake-hook-settings.js +153 -0
- package/dist/lib/wake-hook-settings.js.map +1 -0
- package/dist/lib/wake-state.d.ts +65 -0
- package/dist/lib/wake-state.js +122 -0
- package/dist/lib/wake-state.js.map +1 -0
- package/package.json +5 -2
- package/skills/README.md +1 -1
- package/skills/agent-os/SKILL.md +8 -8
- package/skills/synap/SKILL.md +178 -88
- package/skills/synap/code-skills.md +84 -0
- package/skills/synap/concepts.md +38 -20
- package/skills/synap/creative-loop.md +1 -1
- package/skills/synap/document-embeds.md +17 -1
- package/skills/synap/focus-sessions.md +17 -8
- package/skills/synap/from-intent.md +33 -17
- package/skills/synap/governance-rules.md +3 -1
- package/skills/synap/lenses.md +4 -4
- package/skills/synap/linking.md +2 -2
- package/skills/synap/mental-model.md +1 -1
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/quick-reference.md +2 -1
- package/skills/synap/reflexes.md +8 -8
- package/skills/synap/viewframe-cells.md +1 -1
- package/skills/synap/work-model.md +24 -10
- package/skills/synap/workspace-design.md +5 -5
- package/skills/synap/writes.md +16 -9
- package/skills/synap/writing-titles.md +7 -0
- package/skills/synap-app/SKILL.md +148 -66
- package/skills/synap-app/creating-the-base-app.md +12 -7
- package/skills/synap-app/governance.md +27 -16
- package/skills/synap-app/install-commands.md +18 -9
- package/skills/synap-app/overview.md +16 -9
- package/skills/synap-app/using-the-sdk.md +75 -25
- package/skills/synap-market/SKILL.md +1 -1
- package/skills/synap-market/governance-and-catalog.md +1 -1
- package/skills/synap-schema/SKILL.md +24 -21
- package/skills/synap-schema/intent-vocabulary-ssot.md +24 -21
- package/templates/box/runner.py +206 -0
|
@@ -5,38 +5,49 @@ mutates a Synap pod.
|
|
|
5
5
|
|
|
6
6
|
## The contract
|
|
7
7
|
|
|
8
|
-
Every mutation (`entities.create`, `entities.update`, `relations.create`, …)
|
|
9
|
-
|
|
8
|
+
Every governed mutation (`entities.create`, `entities.update`, `relations.create`, …)
|
|
9
|
+
has one of three outcomes, decided **by the pod**, not by your app:
|
|
10
10
|
|
|
11
|
-
| Outcome |
|
|
11
|
+
| Outcome | How it arrives | What your code should do |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
|
|
|
14
|
-
| `proposed`
|
|
15
|
-
|
|
|
13
|
+
| applied | resolves with the procedure's own status (`"created"`, `"updated"`, …) | proceed |
|
|
14
|
+
| proposed | resolves with `status: "proposed"`, `proposalId`, `reviewUrl`, `message` — queued for the pod owner's review (like a PR) | **surface the review — do NOT treat as failure, do NOT retry** |
|
|
15
|
+
| denied | **rejects** with a tRPC `FORBIDDEN` error whose message is the reason | show why; do not retry blindly |
|
|
16
16
|
|
|
17
17
|
## Why it matters for your code
|
|
18
18
|
|
|
19
19
|
- **Never treat `proposed` as an error.** It is the normal, healthy path for any
|
|
20
20
|
write that governance decides a human should see first. Retrying a `proposed`
|
|
21
21
|
write creates duplicates.
|
|
22
|
-
- **
|
|
23
|
-
|
|
22
|
+
- **A `proposed` result does not throw.** It is a successful response with a
|
|
23
|
+
status; only a denial throws.
|
|
24
24
|
- **Surface the review link/id** so the user can approve it. An unreviewed
|
|
25
25
|
proposal is not yet in the graph — it won't show up in reads until approved.
|
|
26
26
|
|
|
27
27
|
## Pattern
|
|
28
28
|
|
|
29
29
|
```ts
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
import { TRPCClientError } from "@trpc/client";
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
const res = await synap.entities.create.mutate(input);
|
|
34
|
+
if (res.status === "proposed") {
|
|
35
|
+
// tell the user "queued for review"; link res.reviewUrl / res.proposalId.
|
|
36
|
+
// res.entity is null — nothing exists until the proposal is approved.
|
|
37
|
+
} else {
|
|
38
|
+
// "created": res.id / res.entity are live
|
|
39
|
+
}
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (err instanceof TRPCClientError && err.data?.code === "FORBIDDEN") {
|
|
42
|
+
// denied: show err.message; don't retry
|
|
43
|
+
} else throw err;
|
|
35
44
|
}
|
|
36
45
|
```
|
|
37
46
|
|
|
38
47
|
## Idempotency
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
`entities.create` takes no idempotency key. The pod dedups some repeats on its
|
|
50
|
+
own — an identical agent-authored retry within a short window, and creates that
|
|
51
|
+
match an existing entity by identity (a stable `externalId`, or identifying
|
|
52
|
+
properties) — but neither covers every case. Never resend a `proposed` write,
|
|
53
|
+
and when unsure, read back before re-creating.
|
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Scaffold a full app (recommended for a fresh start)
|
|
4
4
|
|
|
5
|
+
> **Not published yet.** The scaffolder (`@synap-core/create-synap-app`) is not
|
|
6
|
+
> on npm and the base template is not public, so `npx` returns 404 today. Use the
|
|
7
|
+
> SDK path below until a release exists.
|
|
8
|
+
|
|
9
|
+
Once published:
|
|
10
|
+
|
|
5
11
|
```bash
|
|
6
|
-
npx create-synap-app my-app
|
|
12
|
+
npx @synap-core/create-synap-app my-app
|
|
7
13
|
```
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
It creates a Next.js + HeroUI project from the base template, with the SDK, auth,
|
|
10
16
|
app shell, command palette, realtime, and mock mode pre-wired. It also drops an
|
|
11
17
|
`AGENTS.md` into the project so your AI coding tool knows how to work with it.
|
|
12
18
|
|
|
@@ -22,24 +28,27 @@ npm install @synap-core/sdk@^1.0.0 @synap-core/react@^1.0.0
|
|
|
22
28
|
# realtime
|
|
23
29
|
npm install @synap-core/sdk-realtime
|
|
24
30
|
|
|
25
|
-
#
|
|
26
|
-
npm install @synap-core/
|
|
31
|
+
# REST client for API-key holders (agents, scripts); also has setupAgent()
|
|
32
|
+
npm install @synap-core/hub-rest-client
|
|
27
33
|
```
|
|
28
34
|
|
|
35
|
+
Do not install `@synap-core/auth` (retired; its last release calls a removed pod
|
|
36
|
+
route) or `@synap-core/auth-bootstrap` (not published).
|
|
37
|
+
|
|
29
38
|
Pin `@^1.0.0` on `sdk`/`react`. **Do not** install unpinned `@synap-core/sdk` —
|
|
30
39
|
older `0.x` versions on the registry are a different, abandoned package.
|
|
31
40
|
|
|
32
41
|
## Get this knowledge into your AI coding tool
|
|
33
42
|
|
|
34
43
|
```bash
|
|
35
|
-
#
|
|
36
|
-
synap
|
|
44
|
+
# print this skill from your pod's skill knowledge base
|
|
45
|
+
synap skill get synap-app
|
|
37
46
|
|
|
38
|
-
# or wire a tool end-to-end (skills + MCP)
|
|
39
|
-
synap connect --target=cursor # or claude, …
|
|
47
|
+
# or wire a tool end-to-end (skills + MCP)
|
|
48
|
+
synap connect --target=cursor # or claude-code, claude-desktop, codex, …
|
|
40
49
|
```
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
Once the scaffolder is published, the scaffolded project ships an `AGENTS.md` at its root — most AI
|
|
43
52
|
coding tools read it automatically, so a freshly-scaffolded app teaches the AI
|
|
44
53
|
how to build on it with zero extra setup.
|
|
45
54
|
|
|
@@ -9,8 +9,8 @@ pod, and **every write is governed** (see `governance.md`).
|
|
|
9
9
|
| The user has… | Do this | Read |
|
|
10
10
|
|---|---|---|
|
|
11
11
|
| an existing app (any framework) | add the SDK | `using-the-sdk.md`, `install-commands.md` |
|
|
12
|
-
| nothing yet, wants a full app fast | scaffold the base app | `creating-the-base-app.md`, `install-commands.md` |
|
|
13
|
-
| a server / script / CLI (no browser) | SDK with a session token or API key | `using-the-sdk.md` |
|
|
12
|
+
| nothing yet, wants a full app fast | scaffold the base app (scaffolder not published yet) | `creating-the-base-app.md`, `install-commands.md` |
|
|
13
|
+
| a server / script / CLI (no browser) | SDK with a session token, or the REST client with an API key | `using-the-sdk.md` |
|
|
14
14
|
|
|
15
15
|
Both paths use the same underlying packages; only the amount of scaffolding differs.
|
|
16
16
|
|
|
@@ -18,9 +18,11 @@ Both paths use the same underlying packages; only the amount of scaffolding diff
|
|
|
18
18
|
|
|
19
19
|
- `@synap-core/sdk` — typed tRPC client. `createSynapClient({ podUrl, ... })`. **The one you almost always want.**
|
|
20
20
|
- `@synap-core/react` — React/TanStack-Query bindings (`SynapProvider`, hooks).
|
|
21
|
-
- `@synap-core/sdk-realtime` — Socket.IO
|
|
22
|
-
- `@synap-core/
|
|
23
|
-
|
|
21
|
+
- `@synap-core/sdk-realtime` — Socket.IO "something changed" events (`createRealtimeClient`).
|
|
22
|
+
- `@synap-core/hub-rest-client` — zero-dep REST client for API-key holders (`HubRestClient`, `setupAgent`).
|
|
23
|
+
|
|
24
|
+
Do not install `@synap-core/auth`: that package was retired, and its last npm
|
|
25
|
+
release signs in through a pod route that no longer exists.
|
|
24
26
|
|
|
25
27
|
Pin `@^1.0.0` on `sdk`/`react` so you never resolve an old, abandoned `0.x`.
|
|
26
28
|
|
|
@@ -30,13 +32,18 @@ Pin `@^1.0.0` on `sdk`/`react` so you never resolve an old, abandoned `0.x`.
|
|
|
30
32
|
the change is queued for the pod owner's review (like a PR). Surface the review,
|
|
31
33
|
don't retry. Full contract: `governance.md`.
|
|
32
34
|
2. **The pod URL has no `/trpc` suffix and no trailing slash.** The SDK appends `/trpc`.
|
|
33
|
-
3. **Non-browser clients (server/CLI/mobile) authenticate with a token or
|
|
34
|
-
never a cookie.
|
|
35
|
+
3. **Non-browser clients (server/CLI/mobile) authenticate with a session token or
|
|
36
|
+
an API key**, never a cookie. An API key only works on the REST client and
|
|
37
|
+
realtime, not on the tRPC SDK. Browser apps use the Kratos session cookie.
|
|
35
38
|
|
|
36
39
|
## Get a pod to build against
|
|
37
40
|
|
|
38
|
-
- **Self-host (free):**
|
|
39
|
-
|
|
41
|
+
- **Self-host (free):** run the backend's `install.sh` (it installs Docker if
|
|
42
|
+
needed, fetches the release bundle, checks it against the release manifest's
|
|
43
|
+
sha256 and runs `synap install`); see the backend's `deploy/README.md`. It
|
|
44
|
+
also checks the manifest's signature: by default
|
|
45
|
+
(`SYNAP_RELEASE_VERIFY=enforce`) it refuses a release whose signature is
|
|
46
|
+
missing or does not verify; `SYNAP_RELEASE_VERIFY=warn` only warns.
|
|
40
47
|
- **Managed (paid):** sign up at synap.live and provision a pod.
|
|
41
48
|
|
|
42
49
|
You can develop the base app with **no pod at all** using its mock mode
|
|
@@ -7,33 +7,41 @@ import { createSynapClient } from "@synap-core/sdk";
|
|
|
7
7
|
|
|
8
8
|
const synap = createSynapClient({
|
|
9
9
|
podUrl: "https://pod.example.com", // NO trailing slash, NO /trpc suffix
|
|
10
|
-
|
|
10
|
+
sessionToken: process.env.SYNAP_SESSION_TOKEN, // see auth below
|
|
11
11
|
workspaceId: process.env.SYNAP_WORKSPACE_ID ?? "",
|
|
12
|
+
onAuthError: () => {/* 401: sign in again */},
|
|
12
13
|
});
|
|
13
14
|
|
|
14
15
|
// It's a typed tRPC client — full autocomplete over every router.
|
|
15
16
|
const me = await synap.users.me.query();
|
|
16
17
|
const entities = await synap.entities.list.query({ /* filter */ });
|
|
17
18
|
const result = await synap.entities.create.mutate({ /* ... */ });
|
|
18
|
-
// result may be
|
|
19
|
+
// result.status may be "proposed" — that is success. See governance.md.
|
|
19
20
|
```
|
|
20
21
|
|
|
21
22
|
### Auth modes (pick ONE)
|
|
22
|
-
- **`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
`@synap-core/
|
|
31
|
-
|
|
23
|
+
- **`sessionToken`** — an Ory Kratos session token from a Kratos API (native)
|
|
24
|
+
login flow, sent as `X-Session-Token`. The normal choice for servers, scripts,
|
|
25
|
+
CLIs and mobile.
|
|
26
|
+
- **cookie fallback** — omit both; the client sends the ambient Kratos cookie
|
|
27
|
+
(`credentials: "include"`). Browser only.
|
|
28
|
+
- **`apiKey`** — only the local-mode token of a desktop pod, sent as
|
|
29
|
+
`Authorization: Bearer`. `/trpc` refuses hub and user API keys
|
|
30
|
+
(keys starting with synap_hub_ or synap_user_), and `createSynapClient` throws if you pass
|
|
31
|
+
one. For an API key, use `@synap-core/hub-rest-client` (below).
|
|
32
|
+
|
|
33
|
+
Other options: `extraHeaders`, and `onAuthError({ status, message })`, called on a
|
|
34
|
+
401 (it also turns the pod's plain-JSON 401 body into a clean tRPC error).
|
|
35
|
+
|
|
36
|
+
To mint an API key for a machine client, `setupAgent(podUrl, provisioningToken,
|
|
37
|
+
agentType)` from `@synap-core/hub-rest-client` returns `{ hubApiKey, agentUserId,
|
|
38
|
+
workspaceId }`. That key works with the REST client and the realtime client, not
|
|
39
|
+
with `/trpc`.
|
|
32
40
|
|
|
33
41
|
## React — `@synap-core/react`
|
|
34
42
|
|
|
35
43
|
```tsx
|
|
36
|
-
import { SynapProvider,
|
|
44
|
+
import { SynapProvider, useSynap, useEntities } from "@synap-core/react";
|
|
37
45
|
|
|
38
46
|
function App() {
|
|
39
47
|
return (
|
|
@@ -42,31 +50,73 @@ function App() {
|
|
|
42
50
|
</SynapProvider>
|
|
43
51
|
);
|
|
44
52
|
}
|
|
53
|
+
|
|
54
|
+
function Dashboard() {
|
|
55
|
+
const { data } = useEntities("note", { limit: 20 }); // thin data hook
|
|
56
|
+
const create = useSynap.entities.create.useMutation(); // raw tRPC hooks
|
|
57
|
+
// …
|
|
58
|
+
}
|
|
45
59
|
```
|
|
46
60
|
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
`useSynap` is the tRPC React hook tree itself — write
|
|
62
|
+
`useSynap.entities.list.useQuery(…)`, **not** `useSynap().entities…`: calling it
|
|
63
|
+
returns `undefined` at runtime (some package docs still show the call form).
|
|
64
|
+
|
|
65
|
+
`SynapProvider` takes every `createSynapClient` option (incl. `sessionToken` and
|
|
66
|
+
`onAuthError`) plus an optional `queryClient` to share an existing TanStack Query
|
|
67
|
+
client. Exports: `SynapProvider`, `useSynapContext` (`{ podUrl, workspaceId }`),
|
|
68
|
+
`useSynap`, the data hooks `useEntity`, `useEntities`, `useLinks`, `useView`,
|
|
69
|
+
and the `RouterInputs` / `RouterOutputs` types. React 18 or 19 is a peer
|
|
70
|
+
dependency — the package does not bundle its own.
|
|
50
71
|
|
|
51
72
|
## Realtime — `@synap-core/sdk-realtime`
|
|
52
73
|
|
|
53
74
|
```ts
|
|
54
75
|
import { createRealtimeClient } from "@synap-core/sdk-realtime";
|
|
55
76
|
|
|
56
|
-
const rt = createRealtimeClient({
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
const rt = createRealtimeClient({
|
|
78
|
+
url: podUrl, // pod base URL; the client adds the /presence namespace
|
|
79
|
+
workspaceId,
|
|
80
|
+
sessionToken, // a Kratos session token…
|
|
81
|
+
userId, // …and the identity id it belongs to (both required)
|
|
82
|
+
// or, as a service account: apiKey (scope realtime:observe), no userId
|
|
83
|
+
onInvalidate: (event) => {
|
|
84
|
+
// entity/relation changed — refetch, e.g.
|
|
85
|
+
queryClient.invalidateQueries({ queryKey: ["entities"] });
|
|
86
|
+
},
|
|
59
87
|
});
|
|
88
|
+
|
|
89
|
+
rt.connect(); // nothing connects until you call this
|
|
90
|
+
// … later
|
|
91
|
+
rt.disconnect();
|
|
60
92
|
```
|
|
61
93
|
|
|
62
|
-
|
|
63
|
-
|
|
94
|
+
- Callbacks (all options, no subscribe methods): `onInvalidate` (the
|
|
95
|
+
entity/relation-changing subset), `onEvent` (every known event, `{ name, data }`),
|
|
96
|
+
`onConnect`, `onDisconnect(reason)`, `onError(error)`.
|
|
97
|
+
- The returned client has `connect()`, `disconnect()`, and read-only `connected`
|
|
98
|
+
and `state` (`"idle" | "connecting" | "connected" | "disconnected"`).
|
|
99
|
+
- `SYNAP_EVENT_NAMES` lists the forwarded events; `ENTITY_INVALIDATING_EVENTS` is
|
|
100
|
+
the subset behind `onInvalidate`.
|
|
101
|
+
- Websocket-only transport (credentials never ride a long-poll URL), and
|
|
102
|
+
`connect()` throws on a non-TLS URL unless you pass `allowInsecure: true`
|
|
103
|
+
(localhost dev only).
|
|
104
|
+
|
|
105
|
+
**Version note.** `@synap-core/sdk-realtime@0.1.0` (the current npm release) sends
|
|
106
|
+
every credential as `auth.token`. The pod reads `{ userId, token, workspaceId }`
|
|
107
|
+
for a user and `{ apiKey, workspaceId }` for a service account, so on 0.1.0 a
|
|
108
|
+
session token works only when you also pass `userId`, and an `apiKey` is always
|
|
109
|
+
refused. The fix — correct handshake keys, plus an up-front throw for no
|
|
110
|
+
credential, both credentials, or `sessionToken` without `userId` — lands in the
|
|
111
|
+
first release after 0.1.0. Until then, authenticate realtime with
|
|
112
|
+
`sessionToken` + `userId`.
|
|
64
113
|
|
|
65
114
|
## Two transports, on purpose
|
|
66
|
-
- `@synap-core/sdk` (tRPC) — for apps. Typed, hooks
|
|
67
|
-
- `@synap-core/hub-rest-client` (REST
|
|
68
|
-
|
|
69
|
-
|
|
115
|
+
- `@synap-core/sdk` (tRPC) — for apps signed in as a user. Typed, React hooks.
|
|
116
|
+
- `@synap-core/hub-rest-client` (REST against `/api/hub/*`, zero-dep) — for
|
|
117
|
+
agents/CLIs/scripts holding an API key. `new HubRestClient({ podUrl, apiKey,
|
|
118
|
+
workspaceId })`. Carries agent verbs the tRPC surface has no first-class path
|
|
119
|
+
for (`ask`, `orient`, `discover`).
|
|
70
120
|
|
|
71
121
|
## Keep types fresh
|
|
72
122
|
The SDK is typed by `@synap-core/api-types`, generated from the pod's live router.
|
|
@@ -622,4 +622,4 @@ wired at every install site). The browser UI is **display-only**: it threads
|
|
|
622
622
|
`requiredTier` through to a "requires <tier>" badge but does NOT hard-block, and
|
|
623
623
|
its lock/upgrade CTA only engages once a host wires a billing destination — so
|
|
624
624
|
don't add a UI-side gate expecting it to enforce anything, and don't rebuild the
|
|
625
|
-
badge thread (it exists). Full current-state:
|
|
625
|
+
badge thread (it exists). Full current-state: the catalog README (`synap-app/packages/workspace-templates/README.md`).
|
|
@@ -60,4 +60,4 @@ wired at every install site). The browser UI is **display-only**: it threads
|
|
|
60
60
|
`requiredTier` through to a "requires <tier>" badge but does NOT hard-block, and
|
|
61
61
|
its lock/upgrade CTA only engages once a host wires a billing destination — so
|
|
62
62
|
don't add a UI-side gate expecting it to enforce anything, and don't rebuild the
|
|
63
|
-
badge thread (it exists). Full current-state:
|
|
63
|
+
badge thread (it exists). Full current-state: the catalog README (`synap-app/packages/workspace-templates/README.md`).
|
|
@@ -315,7 +315,7 @@ Defining a relation def is rarely worth it — `relates_to` + a property usually
|
|
|
315
315
|
|
|
316
316
|
---
|
|
317
317
|
|
|
318
|
-
## The intent vocabulary — one SSOT,
|
|
318
|
+
## The intent vocabulary — one SSOT, two mirrors
|
|
319
319
|
|
|
320
320
|
**What a capability DOES** — `send_message`, `generate_media`, `publish_post`,
|
|
321
321
|
`delegate_agent_task` — is the
|
|
@@ -346,15 +346,17 @@ This is why every code-side copy is a **mirror** and not the source. A slug that
|
|
|
346
346
|
none of the existing rows leaves `intent` UNSET; the vocabulary is deliberately not
|
|
347
347
|
open for developers to mint (cf. W3C Web Intents, abandoned partly for that reason).
|
|
348
348
|
|
|
349
|
-
### The
|
|
349
|
+
### The two mirrors, and why each one must exist
|
|
350
350
|
|
|
351
|
-
There are exactly **
|
|
351
|
+
There are exactly **two**. Two more were removed: `AbstractVerb` in
|
|
352
|
+
`@synap/playbooks` (deleted 2026-10-01, see below), and the pod's own
|
|
353
|
+
`ABSTRACT_VERBS` copy (collapsed 2026-10-26 — `@synap/database` now depends on
|
|
354
|
+
`@synap-core/types`, so it re-exports mirror 1 under that name).
|
|
352
355
|
|
|
353
|
-
| # | Where | Kind
|
|
354
|
-
| --- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
355
|
-
| 1 | `synap-backend/packages/
|
|
356
|
-
| 2 | `synap-
|
|
357
|
-
| 3 | `synap-control-plane-api/src/seeds/capability-intent-vocabulary.ts` — `ABSTRACT_VERBS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, the CP catalog seeder | The control plane is a **separate deploy target with its own `pnpm-lock.yaml`**. It resolves neither `@synap-core/types` nor the pod's packages (verified: `require.resolve('@synap-core/types')` → `MODULE_NOT_FOUND`). |
|
|
356
|
+
| # | Where | Kind | Why it cannot import the SSOT |
|
|
357
|
+
| --- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
358
|
+
| 1 | `synap-backend/packages/types/src/capability-intents/` — `ABSTRACT_INTENTS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, published leaf | The SSOT is SQL rows; a TypeScript list is a mirror by construction. The pod reads it too: `ABSTRACT_VERBS` in `packages/database/src/schema/tools.ts` is this `ABSTRACT_INTENTS`, re-exported (the 0283 SEED union, 13). |
|
|
359
|
+
| 2 | `synap-control-plane-api/src/seeds/capability-intent-vocabulary.ts` — `ABSTRACT_VERBS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, the CP catalog seeder | The control plane is a **separate deploy target with its own `pnpm-lock.yaml`**. It resolves neither `@synap-core/types` nor the pod's packages (verified: `require.resolve('@synap-core/types')` → `MODULE_NOT_FOUND`). |
|
|
358
360
|
|
|
359
361
|
Consumed by: `@synap/api` (`intent-registry`, `create-from-definition`,
|
|
360
362
|
`schemas/playbook-definition.ts`), `synap-app/packages/workspace-templates`
|
|
@@ -377,7 +379,7 @@ Search for this chapter by the field you are holding, not by the word "intent":
|
|
|
377
379
|
All four are validated against this ONE vocabulary, so a workspace and a playbook
|
|
378
380
|
cannot be spelled from two different lists.
|
|
379
381
|
|
|
380
|
-
### THE
|
|
382
|
+
### THE PLAYBOOKS MIRROR WAS DELETED — do not re-add it
|
|
381
383
|
|
|
382
384
|
`AbstractVerb` in `@synap/playbooks/src/index.ts` was a TYPE-only mirror of all 13
|
|
383
385
|
slugs. It was **stale** (no `publish_post`) and **dead** — a whole-repo scan across
|
|
@@ -396,18 +398,19 @@ a package that consumes nothing would go stale in the one direction that is invi
|
|
|
396
398
|
`INSERT INTO "capability_intents" ("slug", "effect", "statement") VALUES (...) ON CONFLICT ("slug") DO NOTHING;`
|
|
397
399
|
`effect` ∈ `read|write|act`. Never `drizzle-kit generate` — hand-write it, and mirror it into
|
|
398
400
|
`0000_baseline_schema.sql` if it adds a table or column.
|
|
399
|
-
2. **Add it to mirror 1** — `
|
|
400
|
-
|
|
401
|
-
`
|
|
402
|
-
Post-seed rows today: `publish_post` (0284, write) and `delegate_agent_task`
|
|
403
|
-
(0314, act — every verb of an external-agent binding, `tools.config.agentBinding`:
|
|
404
|
-
start / send / status / cancel).
|
|
405
|
-
3. **Add it to mirror 2** — `ABSTRACT_INTENTS` or `REGISTERED_EXTRAS` in
|
|
406
|
-
`packages/types/src/capability-intents/index.ts`. Then **`cd packages/types && pnpm build`** —
|
|
401
|
+
2. **Add it to mirror 1** — `ABSTRACT_INTENTS` (a SEED slug) or `REGISTERED_EXTRAS`
|
|
402
|
+
(a post-seed row) in `packages/types/src/capability-intents/index.ts`. The pod's
|
|
403
|
+
`ABSTRACT_VERBS` is `ABSTRACT_INTENTS`, so it follows. Then **`cd packages/types && pnpm build`** —
|
|
407
404
|
consumers typecheck against the built `dist/`, so a skipped rebuild makes your gate lie.
|
|
408
|
-
|
|
405
|
+
Post-seed rows today: `publish_post` (0284, write), `delegate_agent_task`
|
|
406
|
+
(0314, act — every verb of an external-agent binding, `tools.config.agentBinding`:
|
|
407
|
+
start / send / status / cancel), `read_webpage` (0329, read), `search_web`
|
|
408
|
+
(0360, read) and `edit_video` (0370, act — sends the person's video to an
|
|
409
|
+
outside service; its one input, `{ video }`, is seeded on `input_schema` in
|
|
410
|
+
the same file).
|
|
411
|
+
3. **Add it to mirror 2** — the same two lists in the control plane's
|
|
409
412
|
`capability-intent-vocabulary.ts`.
|
|
410
|
-
|
|
413
|
+
4. **Update the arity floors** — `SEED_SLUG_ARITY` / `EXTRA_SLUG_ARITY` in
|
|
411
414
|
`packages/api/src/__tripwires__/intent-vocabulary-one-ssot.tripwire.test.ts`.
|
|
412
415
|
These are the ONE place you must edit by hand, and the build stops until you do.
|
|
413
416
|
|
|
@@ -416,8 +419,8 @@ from the migration SQL, so it is a red build — never a divergence nobody notic
|
|
|
416
419
|
|
|
417
420
|
### What can still go wrong
|
|
418
421
|
|
|
419
|
-
- **A mirror can be added.** Nothing structurally prevents a
|
|
420
|
-
only polices the names it knows. This is why step
|
|
422
|
+
- **A mirror can be added.** Nothing structurally prevents a third copy; the tripwire
|
|
423
|
+
only polices the names it knows. This is why step 4 exists as a hand-edit floor.
|
|
421
424
|
- **A guard proves SAMENESS, never CORRECTNESS.** If every mirror and the migration agree
|
|
422
425
|
on a slug that should not exist, all four guards stay green. The vocabulary's MEANING is
|
|
423
426
|
reviewed by a human, not derived.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## The intent vocabulary — one SSOT,
|
|
1
|
+
## The intent vocabulary — one SSOT, two mirrors
|
|
2
2
|
|
|
3
3
|
**What a capability DOES** — `send_message`, `generate_media`, `publish_post`,
|
|
4
4
|
`delegate_agent_task` — is the
|
|
@@ -29,15 +29,17 @@ This is why every code-side copy is a **mirror** and not the source. A slug that
|
|
|
29
29
|
none of the existing rows leaves `intent` UNSET; the vocabulary is deliberately not
|
|
30
30
|
open for developers to mint (cf. W3C Web Intents, abandoned partly for that reason).
|
|
31
31
|
|
|
32
|
-
### The
|
|
32
|
+
### The two mirrors, and why each one must exist
|
|
33
33
|
|
|
34
|
-
There are exactly **
|
|
34
|
+
There are exactly **two**. Two more were removed: `AbstractVerb` in
|
|
35
|
+
`@synap/playbooks` (deleted 2026-10-01, see below), and the pod's own
|
|
36
|
+
`ABSTRACT_VERBS` copy (collapsed 2026-10-26 — `@synap/database` now depends on
|
|
37
|
+
`@synap-core/types`, so it re-exports mirror 1 under that name).
|
|
35
38
|
|
|
36
|
-
| # | Where | Kind
|
|
37
|
-
| --- | --------------------------------------------------------------------------------------------------------------------------------- |
|
|
38
|
-
| 1 | `synap-backend/packages/
|
|
39
|
-
| 2 | `synap-
|
|
40
|
-
| 3 | `synap-control-plane-api/src/seeds/capability-intent-vocabulary.ts` — `ABSTRACT_VERBS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, the CP catalog seeder | The control plane is a **separate deploy target with its own `pnpm-lock.yaml`**. It resolves neither `@synap-core/types` nor the pod's packages (verified: `require.resolve('@synap-core/types')` → `MODULE_NOT_FOUND`). |
|
|
39
|
+
| # | Where | Kind | Why it cannot import the SSOT |
|
|
40
|
+
| --- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
41
|
+
| 1 | `synap-backend/packages/types/src/capability-intents/` — `ABSTRACT_INTENTS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, published leaf | The SSOT is SQL rows; a TypeScript list is a mirror by construction. The pod reads it too: `ABSTRACT_VERBS` in `packages/database/src/schema/tools.ts` is this `ABSTRACT_INTENTS`, re-exported (the 0283 SEED union, 13). |
|
|
42
|
+
| 2 | `synap-control-plane-api/src/seeds/capability-intent-vocabulary.ts` — `ABSTRACT_VERBS`, `REGISTERED_EXTRAS`, `CAPABILITY_INTENTS` | runtime, the CP catalog seeder | The control plane is a **separate deploy target with its own `pnpm-lock.yaml`**. It resolves neither `@synap-core/types` nor the pod's packages (verified: `require.resolve('@synap-core/types')` → `MODULE_NOT_FOUND`). |
|
|
41
43
|
|
|
42
44
|
Consumed by: `@synap/api` (`intent-registry`, `create-from-definition`,
|
|
43
45
|
`schemas/playbook-definition.ts`), `synap-app/packages/workspace-templates`
|
|
@@ -60,7 +62,7 @@ Search for this chapter by the field you are holding, not by the word "intent":
|
|
|
60
62
|
All four are validated against this ONE vocabulary, so a workspace and a playbook
|
|
61
63
|
cannot be spelled from two different lists.
|
|
62
64
|
|
|
63
|
-
### THE
|
|
65
|
+
### THE PLAYBOOKS MIRROR WAS DELETED — do not re-add it
|
|
64
66
|
|
|
65
67
|
`AbstractVerb` in `@synap/playbooks/src/index.ts` was a TYPE-only mirror of all 13
|
|
66
68
|
slugs. It was **stale** (no `publish_post`) and **dead** — a whole-repo scan across
|
|
@@ -79,18 +81,19 @@ a package that consumes nothing would go stale in the one direction that is invi
|
|
|
79
81
|
`INSERT INTO "capability_intents" ("slug", "effect", "statement") VALUES (...) ON CONFLICT ("slug") DO NOTHING;`
|
|
80
82
|
`effect` ∈ `read|write|act`. Never `drizzle-kit generate` — hand-write it, and mirror it into
|
|
81
83
|
`0000_baseline_schema.sql` if it adds a table or column.
|
|
82
|
-
2. **Add it to mirror 1** — `
|
|
83
|
-
|
|
84
|
-
`
|
|
85
|
-
Post-seed rows today: `publish_post` (0284, write) and `delegate_agent_task`
|
|
86
|
-
(0314, act — every verb of an external-agent binding, `tools.config.agentBinding`:
|
|
87
|
-
start / send / status / cancel).
|
|
88
|
-
3. **Add it to mirror 2** — `ABSTRACT_INTENTS` or `REGISTERED_EXTRAS` in
|
|
89
|
-
`packages/types/src/capability-intents/index.ts`. Then **`cd packages/types && pnpm build`** —
|
|
84
|
+
2. **Add it to mirror 1** — `ABSTRACT_INTENTS` (a SEED slug) or `REGISTERED_EXTRAS`
|
|
85
|
+
(a post-seed row) in `packages/types/src/capability-intents/index.ts`. The pod's
|
|
86
|
+
`ABSTRACT_VERBS` is `ABSTRACT_INTENTS`, so it follows. Then **`cd packages/types && pnpm build`** —
|
|
90
87
|
consumers typecheck against the built `dist/`, so a skipped rebuild makes your gate lie.
|
|
91
|
-
|
|
88
|
+
Post-seed rows today: `publish_post` (0284, write), `delegate_agent_task`
|
|
89
|
+
(0314, act — every verb of an external-agent binding, `tools.config.agentBinding`:
|
|
90
|
+
start / send / status / cancel), `read_webpage` (0329, read), `search_web`
|
|
91
|
+
(0360, read) and `edit_video` (0370, act — sends the person's video to an
|
|
92
|
+
outside service; its one input, `{ video }`, is seeded on `input_schema` in
|
|
93
|
+
the same file).
|
|
94
|
+
3. **Add it to mirror 2** — the same two lists in the control plane's
|
|
92
95
|
`capability-intent-vocabulary.ts`.
|
|
93
|
-
|
|
96
|
+
4. **Update the arity floors** — `SEED_SLUG_ARITY` / `EXTRA_SLUG_ARITY` in
|
|
94
97
|
`packages/api/src/__tripwires__/intent-vocabulary-one-ssot.tripwire.test.ts`.
|
|
95
98
|
These are the ONE place you must edit by hand, and the build stops until you do.
|
|
96
99
|
|
|
@@ -99,8 +102,8 @@ from the migration SQL, so it is a red build — never a divergence nobody notic
|
|
|
99
102
|
|
|
100
103
|
### What can still go wrong
|
|
101
104
|
|
|
102
|
-
- **A mirror can be added.** Nothing structurally prevents a
|
|
103
|
-
only polices the names it knows. This is why step
|
|
105
|
+
- **A mirror can be added.** Nothing structurally prevents a third copy; the tripwire
|
|
106
|
+
only polices the names it knows. This is why step 4 exists as a hand-edit floor.
|
|
104
107
|
- **A guard proves SAMENESS, never CORRECTNESS.** If every mirror and the migration agree
|
|
105
108
|
on a slug that should not exist, all four guards stay green. The vocabulary's MEANING is
|
|
106
109
|
reviewed by a human, not derived.
|