minutework 0.1.46 → 0.1.47
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/assets/claude-local/CLAUDE.md.template +4 -0
- package/assets/claude-local/skills/cross-server-subscriptions/SKILL.md +135 -0
- package/assets/claude-local/skills/dataset-subscriber-flow/SKILL.md +186 -0
- package/assets/claude-local/skills/event-bus/SKILL.md +70 -0
- package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +3 -0
- package/assets/claude-local/skills/runtime-capability-inventory/SKILL.md +20 -12
- package/assets/claude-local/skills/runtime-capability-inventory/primitive-catalog.json +28 -28
- package/dist/cli-json.d.ts +1 -1
- package/dist/cli-json.js.map +1 -1
- package/dist/developer-client.d.ts +29 -0
- package/dist/developer-client.js +35 -0
- package/dist/developer-client.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/workspace.d.ts +3 -0
- package/dist/workspace.js +115 -2
- package/dist/workspace.js.map +1 -1
- package/package.json +3 -3
- package/vendor/workspace-mcp/context.d.ts +4 -1
- package/vendor/workspace-mcp/context.js +4 -0
- package/vendor/workspace-mcp/context.js.map +1 -1
- package/vendor/workspace-mcp/discovery-status.d.ts +16 -0
- package/vendor/workspace-mcp/discovery-status.js +259 -0
- package/vendor/workspace-mcp/discovery-status.js.map +1 -0
- package/vendor/workspace-mcp/index.d.ts +2 -1
- package/vendor/workspace-mcp/index.js +1 -0
- package/vendor/workspace-mcp/index.js.map +1 -1
- package/vendor/workspace-mcp/server.js +9 -1
- package/vendor/workspace-mcp/server.js.map +1 -1
- package/vendor/workspace-mcp/types.d.ts +80 -0
- package/vendor/workspace-mcp/types.js +24 -0
- package/vendor/workspace-mcp/types.js.map +1 -1
|
@@ -69,6 +69,10 @@ coding agent can use them as reference: browse `skills/` and read the relevant
|
|
|
69
69
|
automatically and `/skill-name` invokes one directly; other agents (Codex,
|
|
70
70
|
Cursor) can open the files directly or ask "What skills are available?".
|
|
71
71
|
|
|
72
|
+
When the task involves event-driven behavior or reacting to external/reference
|
|
73
|
+
datasets, read `skills/event-bus/SKILL.md` and
|
|
74
|
+
`skills/cross-server-subscriptions/SKILL.md`.
|
|
75
|
+
|
|
72
76
|
## Capability Gaps
|
|
73
77
|
|
|
74
78
|
When a request exposes missing shared MinuteWork substrate, read
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cross-server-subscriptions
|
|
3
|
+
description: "Reacting to changes in another server's published dataset: discovering dataset publications and declaring cross-server subscription candidates."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Cross-Server Subscriptions
|
|
7
|
+
|
|
8
|
+
Use this skill when the app should react to changes in another server's
|
|
9
|
+
published dataset -- for example keeping a local mirror of a partner's
|
|
10
|
+
registry, directory, or catalog feed in sync.
|
|
11
|
+
|
|
12
|
+
The etiquette is law:
|
|
13
|
+
**install proposes; only operators approve; nothing you build activates a cross-server subscription.**
|
|
14
|
+
Two distinct operator acts stand between your declaration and any delivery.
|
|
15
|
+
|
|
16
|
+
## Discover First
|
|
17
|
+
|
|
18
|
+
Before declaring a candidate, list what the tenant could actually subscribe
|
|
19
|
+
to. Both surfaces are read-only and can never create or activate anything:
|
|
20
|
+
|
|
21
|
+
- Workspace MCP tool: `minutework_discover_dataset_publications`.
|
|
22
|
+
- CLI: `minutework workspace discover-publications [--json]`.
|
|
23
|
+
|
|
24
|
+
Each result row describes one publication: `publication_ref` (the stable
|
|
25
|
+
reference to cite in your candidate reasoning), `event_family`,
|
|
26
|
+
`subject_key`, `event_types`, `residency_classification`, `publisher`
|
|
27
|
+
(`display_name`, `is_self`), and `registered_at`. Rows owned by your own
|
|
28
|
+
tenant additionally carry `status` and `descriptor_digest`.
|
|
29
|
+
|
|
30
|
+
- Discovery is flag-gated platform-side: when the feature is off the platform
|
|
31
|
+
returns HTTP 503 and the tools report an explicit empty list with
|
|
32
|
+
diagnostics, not a guess.
|
|
33
|
+
- HTTP 401 means the developer token is stale: run `minutework login` and
|
|
34
|
+
retry.
|
|
35
|
+
|
|
36
|
+
## Candidate Vocabulary
|
|
37
|
+
|
|
38
|
+
Declare interest with `crossServerSubscriptionCandidates` in
|
|
39
|
+
`schemas/schema.ts` (or `schema.mw`):
|
|
40
|
+
|
|
41
|
+
- `id`: workspace-authored candidate identifier (shares one id namespace with
|
|
42
|
+
`eventSubscriptions`).
|
|
43
|
+
- `eventPattern`: exact `<family>.<verb>` or trailing `<family>.*`. The v1
|
|
44
|
+
family is `dataset` with verbs `records_added` and `snapshot_refreshed`;
|
|
45
|
+
Core's registry, not the compiler, decides which families exist. Because
|
|
46
|
+
the compiler does not validate family names against that registry, a
|
|
47
|
+
candidate that compiles clean can still be rejected at report time as an
|
|
48
|
+
unknown family -- the rejection is receipted for operators and the local
|
|
49
|
+
declaration stays put; the fix is changing the pattern, whose new digest
|
|
50
|
+
reports afresh.
|
|
51
|
+
- `subjectKey`: the correlation key the candidate expects on delivered
|
|
52
|
+
events (match it to the publication's `subject_key`).
|
|
53
|
+
- `publisherHint` (optional): which publisher you expect, as a hint for the
|
|
54
|
+
reviewing operator.
|
|
55
|
+
- `reason` (required): shown verbatim to the reviewing operator. Write it for
|
|
56
|
+
a human: say what the flow does with the data and why the subscription is
|
|
57
|
+
needed, not compiler-speak.
|
|
58
|
+
- `targetFlow`: a flow declared in the same pack; it is what would wake if an
|
|
59
|
+
operator ever approves delivery.
|
|
60
|
+
|
|
61
|
+
Candidates and `eventSubscriptions` share one `(pattern, targetFlow)` pair
|
|
62
|
+
namespace in addition to the id namespace: each candidate compiles to its own
|
|
63
|
+
local subscription half, so declaring an explicit local subscription with the
|
|
64
|
+
same pair is a compile error
|
|
65
|
+
(`compiler.event_subscription.duplicate_pattern_target`). Candidate-implied
|
|
66
|
+
subscriptions carry no filters.
|
|
67
|
+
|
|
68
|
+
## What Install Does -- And Does Not Do
|
|
69
|
+
|
|
70
|
+
At install, each candidate:
|
|
71
|
+
|
|
72
|
+
- Wires its local half: the local subscription that would wake `targetFlow`
|
|
73
|
+
IF the cross-server side is ever operator-approved. The local row alone is
|
|
74
|
+
inert and harmless.
|
|
75
|
+
- Is declared runtime-locally with a declared/reported/withdrawn lifecycle
|
|
76
|
+
keyed by `candidate_digest`. Reinstalling a pack withdraws candidates whose
|
|
77
|
+
digests are absent from the new install.
|
|
78
|
+
- May later be reported upward to Core as a proposal -- that reporting sweep
|
|
79
|
+
is itself flag-gated (`MW_CROSS_SERVER_CANDIDATE_REPORTING_ENABLED`,
|
|
80
|
+
default off). The same sweep reports withdrawals, so a still-pending Core
|
|
81
|
+
proposal is withdrawn when its digest disappears from a reinstall.
|
|
82
|
+
|
|
83
|
+
Operators review reported proposals on the platform operator console. They
|
|
84
|
+
may dismiss a proposal, or promote it into a pending-approval subscription
|
|
85
|
+
that still requires a second digest-checked operator approval before anything
|
|
86
|
+
is active. Promotion scopes that subscription from an active, family-matched
|
|
87
|
+
publisher registration the operator picks -- your `subjectKey` and
|
|
88
|
+
`publisherHint` are advisory input to that choice, not binding scope. Either
|
|
89
|
+
operator decision is durable: re-reporting an unchanged digest is an
|
|
90
|
+
idempotent duplicate and never resurrects a dismissed, promoted, or withdrawn
|
|
91
|
+
proposal. The etiquette again:
|
|
92
|
+
**install proposes; only operators approve; nothing you build activates a cross-server subscription.**
|
|
93
|
+
|
|
94
|
+
Do not present an installed candidate as a working feed. Until both operator
|
|
95
|
+
acts happen, no cross-server event will ever arrive.
|
|
96
|
+
|
|
97
|
+
## Worked Example
|
|
98
|
+
|
|
99
|
+
A subscriber pack that mirrors a generic upstream registry publication: one
|
|
100
|
+
flow and one candidate. The candidate's implied local half is the pack's only
|
|
101
|
+
subscription -- do not also declare an explicit `eventSubscriptions` entry
|
|
102
|
+
with the same `(pattern, targetFlow)` pair; the candidate already implies
|
|
103
|
+
that local half, so the duplicate is a compile error.
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
flows: [
|
|
107
|
+
{
|
|
108
|
+
id: "registry.sync_entry",
|
|
109
|
+
description:
|
|
110
|
+
"Upsert one local mirror entry when upstream registry records change.",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
crossServerSubscriptionCandidates: [
|
|
114
|
+
{
|
|
115
|
+
id: "registry.upstream_feed_candidate",
|
|
116
|
+
eventPattern: "dataset.records_added",
|
|
117
|
+
subjectKey: "entry_ref",
|
|
118
|
+
publisherHint: "partner-registry",
|
|
119
|
+
reason:
|
|
120
|
+
"Keep this tenant's local registry mirror current so member-facing " +
|
|
121
|
+
"lookups reflect the partner registry without manual re-imports.",
|
|
122
|
+
targetFlow: "registry.sync_entry",
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The flow body should be replay-safe (for example, upsert the mirror record
|
|
128
|
+
keyed on the event's opaque record ref) because wake delivery is
|
|
129
|
+
at-least-once with deterministic convergence.
|
|
130
|
+
|
|
131
|
+
## Staleness
|
|
132
|
+
|
|
133
|
+
If this guidance looks stale or the discovery tooling seems missing, refresh
|
|
134
|
+
managed workspace assets with `minutework workspace sync-assets` (see
|
|
135
|
+
`skills/workspace-guidance-refresh/SKILL.md`).
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dataset-subscriber-flow
|
|
3
|
+
description: "A tenant wants their app or agent to react when an external or reference dataset changes: discovery-first subscriber packs over published cross-server datasets."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dataset Subscriber Flow
|
|
7
|
+
|
|
8
|
+
Use this skill when the tenant goal is "react when that external or reference
|
|
9
|
+
dataset changes" -- new records landing in a shared registry, a refreshed
|
|
10
|
+
directory snapshot, a catalog another server publishes. The answer is a
|
|
11
|
+
discovery-first, declarative subscriber pack -- never scraping, polling, or
|
|
12
|
+
replicating the upstream dataset.
|
|
13
|
+
|
|
14
|
+
Work the three steps in order. Do not skip discovery, and do not promise
|
|
15
|
+
activation: that is an operator decision, not a build output.
|
|
16
|
+
|
|
17
|
+
## Step 1 -- Discover
|
|
18
|
+
|
|
19
|
+
Find out what is actually published before designing anything.
|
|
20
|
+
|
|
21
|
+
- From a generated workspace, call the workspace MCP tool
|
|
22
|
+
`minutework_discover_dataset_publications`, or run:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
minutework workspace discover-publications
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
(add `--json` for machine-readable output). Both call the platform
|
|
29
|
+
discovery API with the workspace's tenant-bound developer token. Discovery
|
|
30
|
+
is read-only: listing a publication grants nothing and subscribes to
|
|
31
|
+
nothing.
|
|
32
|
+
- Interpret each result row:
|
|
33
|
+
- `publication_ref` -- the publication's stable opaque handle. Nothing
|
|
34
|
+
links a candidate to a `publication_ref` automatically, so echo the
|
|
35
|
+
matched publication's details into the candidate's `publisherHint` and
|
|
36
|
+
`reason` so the reviewing operator can find it.
|
|
37
|
+
- `event_family` and `event_types` -- what change signals exist. The v1
|
|
38
|
+
family is `dataset` with verbs `dataset.records_added` and
|
|
39
|
+
`dataset.snapshot_refreshed`.
|
|
40
|
+
- `subject_key` -- the correlation key delivered events will carry; your
|
|
41
|
+
candidate's `subjectKey` should match it.
|
|
42
|
+
- `residency_classification` -- how widely the publisher says the data may
|
|
43
|
+
travel; respect it when deciding what to mirror locally.
|
|
44
|
+
- `publisher` (`display_name`, `is_self`) -- who publishes it;
|
|
45
|
+
`is_self` means your own tenant.
|
|
46
|
+
- `registered_at`; own-tenant rows additionally show `status` and
|
|
47
|
+
`descriptor_digest`.
|
|
48
|
+
- Expected failure modes: a `503` means the platform discovery surface is
|
|
49
|
+
flag-gated off; a `401` means the developer token is missing or expired --
|
|
50
|
+
run `minutework login`.
|
|
51
|
+
- If nothing discoverable matches the tenant's dataset, **stop scaffolding**.
|
|
52
|
+
Do not improvise an ingestion path: no scraping the upstream surface, no
|
|
53
|
+
polling its APIs, no replicating its data into local records. Route to an
|
|
54
|
+
operator conversation instead -- record the missing publication as a
|
|
55
|
+
capability gap (see `skills/capability-gap-reporting/SKILL.md`) and let
|
|
56
|
+
humans decide whether the upstream side should publish.
|
|
57
|
+
|
|
58
|
+
## Step 2 -- Scaffold The Subscriber Pack
|
|
59
|
+
|
|
60
|
+
Build the subscriber declaratively in the workspace schema source
|
|
61
|
+
(`schemas/schema.ts` or `schema.mw`) using three vocabulary keys: `flows`
|
|
62
|
+
(compiled to `FlowManifestV1` documents) plus `eventSubscriptions` and
|
|
63
|
+
`crossServerSubscriptionCandidates` (compiled together into
|
|
64
|
+
`eventSubscriptionManifests` documents, `EventSubscriptionManifestV1`):
|
|
65
|
+
|
|
66
|
+
- `flows`: `[{ id, description?, definition? }]` -- the local flow the event
|
|
67
|
+
wakes.
|
|
68
|
+
- `eventSubscriptions`: `[{ id, eventTypePattern, targetFlow, filters? }]` --
|
|
69
|
+
local wiring for events that already reach this runtime (also valid on
|
|
70
|
+
connector packs). For cross-server dataset events you usually do not need
|
|
71
|
+
one: the candidate below implies it.
|
|
72
|
+
- `crossServerSubscriptionCandidates`:
|
|
73
|
+
`[{ id, eventPattern, subjectKey, publisherHint?, reason, targetFlow }]` --
|
|
74
|
+
the proposal that a human operator will review.
|
|
75
|
+
|
|
76
|
+
Generic worked sketch (a tenant whose app should react when a shared
|
|
77
|
+
directory server publishes new registry entries):
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
flows: [
|
|
81
|
+
{
|
|
82
|
+
id: "flow.registry_change_intake",
|
|
83
|
+
description: "Mirror new upstream registry entries into local records.",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
crossServerSubscriptionCandidates: [
|
|
87
|
+
{
|
|
88
|
+
id: "cand.registry_records_added",
|
|
89
|
+
eventPattern: "dataset.records_added",
|
|
90
|
+
subjectKey: "registry_entry_id",
|
|
91
|
+
publisherHint: "shared-directory-server",
|
|
92
|
+
reason:
|
|
93
|
+
"Keep this tenant's local supplier catalog current by waking the " +
|
|
94
|
+
"registry intake flow when the upstream directory publishes new " +
|
|
95
|
+
"entries; without it the catalog goes stale between manual checks.",
|
|
96
|
+
targetFlow: "flow.registry_change_intake",
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
There is deliberately no plain `eventSubscriptions` entry in this sketch: the
|
|
102
|
+
candidate alone compiles the local subscription half that wakes
|
|
103
|
+
`flow.registry_change_intake`. The implied local half carries no `filters`,
|
|
104
|
+
so any narrowing (for example, reacting only to `supplier` entries) belongs
|
|
105
|
+
inside the woken flow.
|
|
106
|
+
|
|
107
|
+
Authoring rules the compiler enforces:
|
|
108
|
+
|
|
109
|
+
- Patterns are exact `<family>.<verb>` or a trailing `<family>.*` only; no
|
|
110
|
+
embedded `*`. The compiler does NOT validate family names against Core's
|
|
111
|
+
registry -- Core is the single source of truth for which families exist.
|
|
112
|
+
- Filter operators are the verbatim runtime vocabulary: `eq`, `neq`, `in`,
|
|
113
|
+
`not_in`, `gt`, `gte`, `lt`, `lte`, `contains`, `starts_with`. Filters AND
|
|
114
|
+
together.
|
|
115
|
+
- Duplicate `(pattern, targetFlow)` pairs and duplicate filters are compile
|
|
116
|
+
errors; `targetFlow` must name a flow in the same pack.
|
|
117
|
+
- Candidates count toward the `(pattern, targetFlow)` pairs -- each candidate
|
|
118
|
+
compiles its own local subscription half (with no filters) -- so do not
|
|
119
|
+
also declare a plain `eventSubscription` for the same pair.
|
|
120
|
+
- Write the candidate `reason` for the human operator who will review it: say
|
|
121
|
+
what the flow does with the events and why the tenant needs them. It is
|
|
122
|
+
shown verbatim to the reviewer; a vague reason earns a dismissal.
|
|
123
|
+
|
|
124
|
+
Keep the woken flow replay-safe (delivery is at-least-once): idempotent local
|
|
125
|
+
record upserts keyed on the event's record reference, and any effectful
|
|
126
|
+
follow-up the flow proposes parks in the existing human-approval loop rather
|
|
127
|
+
than executing directly.
|
|
128
|
+
|
|
129
|
+
## Step 3 -- Etiquette
|
|
130
|
+
|
|
131
|
+
**install proposes; only operators approve; nothing you build activates a cross-server subscription.**
|
|
132
|
+
|
|
133
|
+
State this plainly to the tenant. What install actually does:
|
|
134
|
+
|
|
135
|
+
- A candidate implies its local half: install wires the
|
|
136
|
+
`LocalEventSubscription` that will wake the flow IF the cross-server side
|
|
137
|
+
is ever operator-approved. The local row alone is inert and harmless --
|
|
138
|
+
firing additionally requires the pack to be `ACTIVE` and is globally gated
|
|
139
|
+
by the runtime flag `MW_LOCAL_EVENT_DISPATCH_ENABLED` (default off). A wake
|
|
140
|
+
is a deterministic flow-start job per (event, subscription).
|
|
141
|
+
- Subscriptions are replaced per pack at install; an invalid target flow
|
|
142
|
+
fails the whole install. Candidates are stored runtime-locally with a
|
|
143
|
+
declared/reported/withdrawn lifecycle keyed by `candidate_digest`;
|
|
144
|
+
reinstalling withdraws digests no longer declared (withdrawals are reported
|
|
145
|
+
upward too, withdrawing a still-pending Core proposal).
|
|
146
|
+
- Two operator acts stand between your candidate and a live subscription:
|
|
147
|
+
stored candidates are reported upward by a flag-gated runtime sweep
|
|
148
|
+
(`MW_CROSS_SERVER_CANDIDATE_REPORTING_ENABLED`, default off) to Core
|
|
149
|
+
proposals; operators review them on the platform operator console, where
|
|
150
|
+
promoting yields a pending-approval subscription that STILL requires a
|
|
151
|
+
second digest-checked operator approval (or they dismiss the proposal).
|
|
152
|
+
Either decision is durable: re-reporting an unchanged digest is an
|
|
153
|
+
idempotent duplicate and never resurrects a dismissed, promoted, or
|
|
154
|
+
withdrawn proposal -- a fresh proposal needs changed digest-covered content
|
|
155
|
+
(`eventPattern`, `subjectKey`, or `targetFlow`).
|
|
156
|
+
- Delivery also requires the publisher side to be active and approved. Even a
|
|
157
|
+
fully approved subscriber receives nothing until the publishing server's
|
|
158
|
+
side is live.
|
|
159
|
+
|
|
160
|
+
Never instruct or attempt any of the following: creating or activating a
|
|
161
|
+
cross-server subscription, calling operator review or posture APIs, or
|
|
162
|
+
presenting an installed candidate as a working integration. The honest status
|
|
163
|
+
after install is "proposed, awaiting operator review."
|
|
164
|
+
|
|
165
|
+
## Disqualifiers
|
|
166
|
+
|
|
167
|
+
- **Bulk data movement.** If the tenant wants dataset slices copied locally,
|
|
168
|
+
that is the explicit grant-scoped import/copy flow, not a subscription.
|
|
169
|
+
Subscriptions deliver change signals, not the dataset.
|
|
170
|
+
- **No discoverable publication.** Route to an operator conversation via the
|
|
171
|
+
capability-gap path (Step 1); never scrape, poll, or replicate.
|
|
172
|
+
- **Per-customer deliverables.** Outputs for each of the tenant's customers
|
|
173
|
+
should be runtime content/workflow outputs produced through the installed
|
|
174
|
+
pack, not a new pack per customer.
|
|
175
|
+
|
|
176
|
+
## Related Skills
|
|
177
|
+
|
|
178
|
+
- `skills/cross-server-subscriptions/SKILL.md` -- the full vocabulary and
|
|
179
|
+
lifecycle detail behind candidates, proposals, and approvals.
|
|
180
|
+
- `skills/event-bus/SKILL.md` -- runtime-local event wiring the woken flow
|
|
181
|
+
builds on.
|
|
182
|
+
- `skills/capability-gap-reporting/SKILL.md` -- recording the gap when no
|
|
183
|
+
publication exists.
|
|
184
|
+
- If this skill is missing from an older generated workspace, refresh managed
|
|
185
|
+
guidance with `minutework workspace sync-assets`
|
|
186
|
+
(see `skills/workspace-guidance-refresh/SKILL.md`).
|
|
@@ -11,3 +11,73 @@ Use runtime-local events for decoupled app behavior.
|
|
|
11
11
|
- Keep private payloads, traces, and detailed execution state runtime-local.
|
|
12
12
|
- Project only safe receipts or summaries outward when required.
|
|
13
13
|
- Use explicit filters and targets instead of broad catch-all handlers.
|
|
14
|
+
|
|
15
|
+
## Source Vocabulary
|
|
16
|
+
|
|
17
|
+
Declare event-driven behavior in `schemas/schema.ts` (or `schema.mw`):
|
|
18
|
+
|
|
19
|
+
- `flows`: `[{ id, description?, definition? }]` -- the runnable targets that
|
|
20
|
+
subscriptions wake.
|
|
21
|
+
- `eventSubscriptions`: `[{ id, eventTypePattern, targetFlow, filters? }]` --
|
|
22
|
+
local subscriptions. Also valid on connector packs.
|
|
23
|
+
|
|
24
|
+
Minimal example:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
flows: [
|
|
28
|
+
{
|
|
29
|
+
id: "registry.refresh_entry",
|
|
30
|
+
description: "Refresh one cached directory entry.",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
eventSubscriptions: [
|
|
34
|
+
{
|
|
35
|
+
id: "registry.entry_updated_sub",
|
|
36
|
+
eventTypePattern: "directory.entry_updated",
|
|
37
|
+
targetFlow: "registry.refresh_entry",
|
|
38
|
+
filters: [
|
|
39
|
+
{ field_path: "payload.status", operator: "eq", value: "active" },
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Pattern Rules
|
|
46
|
+
|
|
47
|
+
- Patterns are exact `<family>.<verb>` or a trailing `<family>.*` wildcard
|
|
48
|
+
only. No embedded `*`, no bare `*`.
|
|
49
|
+
- The compiler does not validate family names against Core's registry; Core
|
|
50
|
+
is the single source of truth for which event families exist.
|
|
51
|
+
|
|
52
|
+
## Filters
|
|
53
|
+
|
|
54
|
+
- Operators (verbatim runtime vocabulary): `eq`, `neq`, `in`, `not_in`, `gt`,
|
|
55
|
+
`gte`, `lt`, `lte`, `contains`, `starts_with`.
|
|
56
|
+
- Multiple filters on one subscription AND together: an event must satisfy
|
|
57
|
+
every filter to wake the target flow.
|
|
58
|
+
- Duplicate `(pattern, targetFlow)` pairs and duplicate filters are compile
|
|
59
|
+
errors. `targetFlow` must name a flow declared in the same pack.
|
|
60
|
+
- Cross-server subscription candidates share the same id namespace and count
|
|
61
|
+
toward `(pattern, targetFlow)` uniqueness, because each candidate implies
|
|
62
|
+
its local subscription half (see
|
|
63
|
+
`skills/cross-server-subscriptions/SKILL.md`).
|
|
64
|
+
|
|
65
|
+
## Dispatch Behavior
|
|
66
|
+
|
|
67
|
+
- Subscriptions compile into the `eventSubscriptionManifests` document kind
|
|
68
|
+
and materialize as local subscription rows at install.
|
|
69
|
+
- Flow targets only in v1: a matching event starts the target flow through a
|
|
70
|
+
deterministic flow-start job per `(event, subscription)` pair, so replays
|
|
71
|
+
converge on one run instead of double-firing.
|
|
72
|
+
- Firing requires the owning pack to be ACTIVE and is globally gated by the
|
|
73
|
+
runtime flag `MW_LOCAL_EVENT_DISPATCH_ENABLED` (default off).
|
|
74
|
+
|
|
75
|
+
## Install Semantics
|
|
76
|
+
|
|
77
|
+
- Install replaces a pack's subscriptions wholesale (delete-and-recreate per
|
|
78
|
+
pack, mirroring sidecar registrations).
|
|
79
|
+
- An invalid target flow fails the whole install -- no partial wiring, no
|
|
80
|
+
partial activation.
|
|
81
|
+
|
|
82
|
+
For anything that crosses server boundaries (reacting to another server's
|
|
83
|
+
published dataset), read `skills/cross-server-subscriptions/SKILL.md`.
|
|
@@ -37,6 +37,9 @@ needed:
|
|
|
37
37
|
- `sidecar-generation/SKILL.md` for bridge/integration execution, workers,
|
|
38
38
|
webhooks, schedulers, and backend compute.
|
|
39
39
|
- `standalone-mobile-client/SKILL.md` for Expo/native client boundaries.
|
|
40
|
+
- `dataset-subscriber-flow/SKILL.md` for reacting to published cross-server
|
|
41
|
+
dataset changes: discovery-first subscriber packs, cross-server candidates,
|
|
42
|
+
and the operator-approval etiquette.
|
|
40
43
|
- `ontology-mapping/SKILL.md` for shared URNs, overlays, explicit promotion,
|
|
41
44
|
and the data network-effect story.
|
|
42
45
|
- `shadow-participation-and-guest-threads/SKILL.md` for guests, external
|
|
@@ -87,6 +87,9 @@ generated Builder workspace.
|
|
|
87
87
|
- Collaboration, shadow identity, alias ingress, ontology ownership, and
|
|
88
88
|
thread-routing questions are usually implemented-system questions. Prefer
|
|
89
89
|
source inspection over MCP-only inference for those.
|
|
90
|
+
- For reacting to published cross-server dataset changes (discovery-first
|
|
91
|
+
subscriber packs, cross-server candidates, and the operator-approval
|
|
92
|
+
etiquette), route to `skills/dataset-subscriber-flow/SKILL.md`.
|
|
90
93
|
- The gap report contract lives at `.minutework/runtime/capability-gap-report.json`.
|
|
91
94
|
|
|
92
95
|
## Known Seeded Primitive Catalog
|
|
@@ -124,10 +127,21 @@ generated Builder workspace.
|
|
|
124
127
|
connection/secret availability.
|
|
125
128
|
- `integrations.execute_automation` -- Approval is definition-forced in
|
|
126
129
|
mw.core.agent_actions (a definition can force approval, never relax it).
|
|
130
|
+
- `communication.send_email` -- Real provider send (Resend) registered as a metered
|
|
131
|
+
action capability; preflight fail-closes on connection/secret availability, and the
|
|
132
|
+
delivery row is idempotent on the ActionRun id with a SENT short-circuit. Not
|
|
133
|
+
agent-exposed yet: exposure is a separate per-definition mw.core.agent_actions flip.
|
|
134
|
+
- `communication.send_sms` -- Real provider send (Twilio) registered as a metered
|
|
135
|
+
action capability; preflight fail-closes on connection/secret availability, and the
|
|
136
|
+
delivery row is idempotent on the ActionRun id with a SENT short-circuit. Not
|
|
137
|
+
agent-exposed yet: exposure is a separate per-definition mw.core.agent_actions flip.
|
|
127
138
|
- `consent.check_channel` -- Service seam consumed by other executors and sidecars as
|
|
128
139
|
a preflight; not an agent-callable tool.
|
|
129
140
|
- `discovery.request_proposal` -- Effectful; outside the default READ_RING, granted
|
|
130
141
|
per agent via enable_agent_tools (BUILDER_DELEGATION_RING member).
|
|
142
|
+
- `ontology.resolve_local` -- Read-only native tool over
|
|
143
|
+
URNAnchor/LocalOntologyMapping; not in the default READ_RING, granted per agent via
|
|
144
|
+
enable_agent_tools.
|
|
131
145
|
- `command_exec.run_template` -- Operator/platform-dispatch surface; not an
|
|
132
146
|
agent-callable tool.
|
|
133
147
|
- `voice.hangup_call` -- VoiceSession finalization is live; the provider-side hangup
|
|
@@ -138,6 +152,12 @@ generated Builder workspace.
|
|
|
138
152
|
leg as unavailable):
|
|
139
153
|
- `scheduling.book_appointment` -- Capability is registered but the direct booking
|
|
140
154
|
executor is MVP-deferred; preflight truthfully reports provider_unavailable.
|
|
155
|
+
- `ontology.propose_candidate` -- Staging leg only: records a PENDING
|
|
156
|
+
PromotionCandidate locally (idempotent on origin_ref+candidate_kind). The
|
|
157
|
+
cross-plane submission to Core (PENDING -> SUBMITTED -> resolved with a minted
|
|
158
|
+
core_urn) is a deferred, bridge-owned leg; the promotion service stays
|
|
159
|
+
platform-owned. Effectful; outside the default READ_RING, granted per agent via
|
|
160
|
+
enable_agent_tools.
|
|
141
161
|
- `voice.initiate_call` -- Pre-dial stack is live (consent + TCPA preflight, approval
|
|
142
162
|
parking, VoiceSession lifecycle); the Twilio dial + realtime media worker are
|
|
143
163
|
platform-owned Phase 4.
|
|
@@ -146,16 +166,4 @@ generated Builder workspace.
|
|
|
146
166
|
- `projection.publish_receipt` -- Owning services emit receipts through the runtime
|
|
147
167
|
bridge directly (e.g. command_exec posts its own run receipts); do not build a
|
|
148
168
|
bespoke generic receipt executor.
|
|
149
|
-
- `communication.send_email` -- Sidecar bridge mirroring the
|
|
150
|
-
runtime_bridge/integrations transport seam with a consent.check_channel preflight;
|
|
151
|
-
route sends through the send_notification seam, never inline in runtime. End-state
|
|
152
|
-
is an action capability like voice.initiate_call.
|
|
153
|
-
- `communication.send_sms` -- Sidecar bridge mirroring the runtime_bridge/integrations
|
|
154
|
-
transport seam with a consent.check_channel preflight; route sends through the
|
|
155
|
-
send_notification seam, never inline in runtime. End-state is an action capability
|
|
156
|
-
like voice.initiate_call.
|
|
157
|
-
- `ontology.resolve_local` -- Seed URNAnchor rows at install; treat resolution as a
|
|
158
|
-
read-only lookup over seeded anchors.
|
|
159
|
-
- `ontology.propose_candidate` -- Stage PromotionCandidate rows for manual review; the
|
|
160
|
-
promotion service is platform-owned, do not build it tenant-side.
|
|
161
169
|
<!-- builder-doc-sync:active-primitives:end -->
|
|
@@ -190,13 +190,13 @@
|
|
|
190
190
|
"requires_integration": true,
|
|
191
191
|
"requires_secret": true,
|
|
192
192
|
"metered": true,
|
|
193
|
-
"executor_ready": "
|
|
194
|
-
"executor_ref": "",
|
|
195
|
-
"executor_notes": "
|
|
193
|
+
"executor_ready": "live",
|
|
194
|
+
"executor_ref": "capability:communication.send_email",
|
|
195
|
+
"executor_notes": "Real provider send (Resend) registered as a metered action capability; preflight fail-closes on connection/secret availability, and the delivery row is idempotent on the ActionRun id with a SENT short-circuit. Not agent-exposed yet: exposure is a separate per-definition mw.core.agent_actions flip.",
|
|
196
196
|
"agent_exposable": false,
|
|
197
197
|
"agent_exposure_path": "none",
|
|
198
|
-
"approval_required":
|
|
199
|
-
"interim_path": "
|
|
198
|
+
"approval_required": false,
|
|
199
|
+
"interim_path": ""
|
|
200
200
|
},
|
|
201
201
|
{
|
|
202
202
|
"primitive_id": "communication.send_sms",
|
|
@@ -209,13 +209,13 @@
|
|
|
209
209
|
"requires_integration": true,
|
|
210
210
|
"requires_secret": true,
|
|
211
211
|
"metered": true,
|
|
212
|
-
"executor_ready": "
|
|
213
|
-
"executor_ref": "",
|
|
214
|
-
"executor_notes": "
|
|
212
|
+
"executor_ready": "live",
|
|
213
|
+
"executor_ref": "capability:communication.send_sms",
|
|
214
|
+
"executor_notes": "Real provider send (Twilio) registered as a metered action capability; preflight fail-closes on connection/secret availability, and the delivery row is idempotent on the ActionRun id with a SENT short-circuit. Not agent-exposed yet: exposure is a separate per-definition mw.core.agent_actions flip.",
|
|
215
215
|
"agent_exposable": false,
|
|
216
216
|
"agent_exposure_path": "none",
|
|
217
|
-
"approval_required":
|
|
218
|
-
"interim_path": "
|
|
217
|
+
"approval_required": false,
|
|
218
|
+
"interim_path": ""
|
|
219
219
|
},
|
|
220
220
|
{
|
|
221
221
|
"primitive_id": "consent.check_channel",
|
|
@@ -278,39 +278,39 @@
|
|
|
278
278
|
"primitive_id": "ontology.resolve_local",
|
|
279
279
|
"family": "ontology",
|
|
280
280
|
"display_name": "Resolve Local Ontology",
|
|
281
|
-
"description": "Resolve a local record against the ontology
|
|
282
|
-
"runtime_app": "
|
|
281
|
+
"description": "Resolve a local record against the shared ontology: its fields' Core URN anchors, with app-pack kind mappings as fallback candidates.",
|
|
282
|
+
"runtime_app": "runtime_ontology",
|
|
283
283
|
"dispatch_path": "",
|
|
284
284
|
"status": "active",
|
|
285
285
|
"requires_integration": false,
|
|
286
286
|
"requires_secret": false,
|
|
287
287
|
"metered": false,
|
|
288
|
-
"executor_ready": "
|
|
289
|
-
"executor_ref": "",
|
|
290
|
-
"executor_notes": "
|
|
291
|
-
"agent_exposable":
|
|
292
|
-
"agent_exposure_path": "
|
|
293
|
-
"approval_required":
|
|
294
|
-
"interim_path": "
|
|
288
|
+
"executor_ready": "live",
|
|
289
|
+
"executor_ref": "tool:ontology.resolve_local",
|
|
290
|
+
"executor_notes": "Read-only native tool over URNAnchor/LocalOntologyMapping; not in the default READ_RING, granted per agent via enable_agent_tools.",
|
|
291
|
+
"agent_exposable": true,
|
|
292
|
+
"agent_exposure_path": "native_tool",
|
|
293
|
+
"approval_required": false,
|
|
294
|
+
"interim_path": ""
|
|
295
295
|
},
|
|
296
296
|
{
|
|
297
297
|
"primitive_id": "ontology.propose_candidate",
|
|
298
298
|
"family": "ontology",
|
|
299
299
|
"display_name": "Propose Ontology Candidate",
|
|
300
|
-
"description": "
|
|
301
|
-
"runtime_app": "
|
|
300
|
+
"description": "Stage a promotion candidate proposing a local entity/person/location for shared ontology acceptance.",
|
|
301
|
+
"runtime_app": "runtime_ontology",
|
|
302
302
|
"dispatch_path": "",
|
|
303
303
|
"status": "active",
|
|
304
304
|
"requires_integration": false,
|
|
305
305
|
"requires_secret": false,
|
|
306
306
|
"metered": false,
|
|
307
|
-
"executor_ready": "
|
|
308
|
-
"executor_ref": "",
|
|
309
|
-
"executor_notes": "
|
|
310
|
-
"agent_exposable":
|
|
311
|
-
"agent_exposure_path": "
|
|
312
|
-
"approval_required":
|
|
313
|
-
"interim_path": "
|
|
307
|
+
"executor_ready": "partial",
|
|
308
|
+
"executor_ref": "tool:ontology.propose_candidate",
|
|
309
|
+
"executor_notes": "Staging leg only: records a PENDING PromotionCandidate locally (idempotent on origin_ref+candidate_kind). The cross-plane submission to Core (PENDING -> SUBMITTED -> resolved with a minted core_urn) is a deferred, bridge-owned leg; the promotion service stays platform-owned. Effectful; outside the default READ_RING, granted per agent via enable_agent_tools.",
|
|
310
|
+
"agent_exposable": true,
|
|
311
|
+
"agent_exposure_path": "native_tool",
|
|
312
|
+
"approval_required": false,
|
|
313
|
+
"interim_path": ""
|
|
314
314
|
},
|
|
315
315
|
{
|
|
316
316
|
"primitive_id": "command_exec.run_template",
|
package/dist/cli-json.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const CLI_JSON_VERSION: 1;
|
|
2
|
-
export type CliJsonCommand = "validate" | "compile" | "codegen" | "deploy" | "publish" | "gaps" | "sandbox";
|
|
2
|
+
export type CliJsonCommand = "validate" | "compile" | "codegen" | "deploy" | "publish" | "gaps" | "sandbox" | "workspace";
|
|
3
3
|
export type CliJsonEnvelope = {
|
|
4
4
|
cliJsonVersion: typeof CLI_JSON_VERSION;
|
|
5
5
|
command: CliJsonCommand;
|
package/dist/cli-json.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-json.js","sourceRoot":"","sources":["../src/cli-json.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-json.js","sourceRoot":"","sources":["../src/cli-json.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAU,CAAC;AAqB3C;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAMrC;IACC,MAAM,OAAO,GAAoB;QAC/B,cAAc,EAAE,gBAAgB;QAChC,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,IAAI;QAC/B,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,IAAI;KAC9B,CAAC;IACF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC"}
|
|
@@ -217,6 +217,34 @@ export type AgentEventsResponse = {
|
|
|
217
217
|
next_after_sequence: number;
|
|
218
218
|
thread_id: string;
|
|
219
219
|
};
|
|
220
|
+
/**
|
|
221
|
+
* One subscribable dataset publication row from the platform discovery read
|
|
222
|
+
* (`/api/v1/cross-server-events/discovery/publications/`). The keys mirror
|
|
223
|
+
* the platform's reviewed cross-tenant field whitelist exactly, and the row
|
|
224
|
+
* shape is normalized to match the workspace MCP discovery tool
|
|
225
|
+
* (`minutework_discover_dataset_publications`) so both readers of the
|
|
226
|
+
* endpoint share one effective contract: own-tenant-only fields (`status`,
|
|
227
|
+
* `descriptor_digest`) are explicit `null` on cross-tenant rows, never
|
|
228
|
+
* absent keys. Discovery is read-only posture: nothing on this surface can
|
|
229
|
+
* create or activate a cross-server subscription.
|
|
230
|
+
*/
|
|
231
|
+
export type DeveloperDiscoverableDatasetPublication = {
|
|
232
|
+
descriptor_digest: string | null;
|
|
233
|
+
event_family: string;
|
|
234
|
+
event_types: string[];
|
|
235
|
+
publication_ref: string;
|
|
236
|
+
publisher: {
|
|
237
|
+
display_name: string;
|
|
238
|
+
is_self: boolean;
|
|
239
|
+
};
|
|
240
|
+
registered_at: string;
|
|
241
|
+
residency_classification: string;
|
|
242
|
+
status: string | null;
|
|
243
|
+
subject_key: string;
|
|
244
|
+
};
|
|
245
|
+
export type DeveloperDatasetPublicationDiscoveryResponse = {
|
|
246
|
+
publications: DeveloperDiscoverableDatasetPublication[];
|
|
247
|
+
};
|
|
220
248
|
export type DeveloperClientDependencies = {
|
|
221
249
|
fetchImpl?: typeof fetch;
|
|
222
250
|
};
|
|
@@ -310,6 +338,7 @@ export declare function createDeveloperClient(options: {
|
|
|
310
338
|
sourceKind?: string;
|
|
311
339
|
status?: string;
|
|
312
340
|
}): Promise<DeveloperBuilderCapabilityRequestListResponse>;
|
|
341
|
+
listDiscoverableDatasetPublications(): Promise<DeveloperDatasetPublicationDiscoveryResponse>;
|
|
313
342
|
attachAgent(): Promise<AgentAttachResponse>;
|
|
314
343
|
resumeAgent(): Promise<AgentAttachResponse>;
|
|
315
344
|
getAgentStatus(): Promise<AgentStatusResponse>;
|