minutework 0.1.45 → 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.
Files changed (40) hide show
  1. package/assets/claude-local/CLAUDE.md.template +10 -0
  2. package/assets/claude-local/skills/README.md +1 -0
  3. package/assets/claude-local/skills/ai-capability-defaults/SKILL.md +2 -0
  4. package/assets/claude-local/skills/cross-server-subscriptions/SKILL.md +135 -0
  5. package/assets/claude-local/skills/dataset-subscriber-flow/SKILL.md +186 -0
  6. package/assets/claude-local/skills/event-bus/SKILL.md +70 -0
  7. package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +3 -0
  8. package/assets/claude-local/skills/runtime-capability-inventory/SKILL.md +74 -15
  9. package/assets/claude-local/skills/runtime-capability-inventory/primitive-catalog.json +392 -0
  10. package/assets/claude-local/skills/runtime-primitive-interim-paths/SKILL.md +96 -0
  11. package/dist/cli-json.d.ts +1 -1
  12. package/dist/cli-json.js.map +1 -1
  13. package/dist/developer-client.d.ts +29 -0
  14. package/dist/developer-client.js +35 -0
  15. package/dist/developer-client.js.map +1 -1
  16. package/dist/index.d.ts +2 -0
  17. package/dist/index.js +5 -2
  18. package/dist/index.js.map +1 -1
  19. package/dist/workspace.d.ts +3 -0
  20. package/dist/workspace.js +115 -2
  21. package/dist/workspace.js.map +1 -1
  22. package/package.json +2 -2
  23. package/vendor/workspace-mcp/context.d.ts +7 -1
  24. package/vendor/workspace-mcp/context.js +8 -0
  25. package/vendor/workspace-mcp/context.js.map +1 -1
  26. package/vendor/workspace-mcp/discovery-status.d.ts +16 -0
  27. package/vendor/workspace-mcp/discovery-status.js +259 -0
  28. package/vendor/workspace-mcp/discovery-status.js.map +1 -0
  29. package/vendor/workspace-mcp/index.d.ts +3 -1
  30. package/vendor/workspace-mcp/index.js +2 -0
  31. package/vendor/workspace-mcp/index.js.map +1 -1
  32. package/vendor/workspace-mcp/primitive-status.d.ts +7 -0
  33. package/vendor/workspace-mcp/primitive-status.js +380 -0
  34. package/vendor/workspace-mcp/primitive-status.js.map +1 -0
  35. package/vendor/workspace-mcp/server.d.ts +1 -0
  36. package/vendor/workspace-mcp/server.js +17 -1
  37. package/vendor/workspace-mcp/server.js.map +1 -1
  38. package/vendor/workspace-mcp/types.d.ts +184 -0
  39. package/vendor/workspace-mcp/types.js +62 -0
  40. package/vendor/workspace-mcp/types.js.map +1 -1
@@ -42,6 +42,12 @@ workspace state. It is wired for Cursor (`.cursor/mcp.json`) and Codex
42
42
  `mcp/claude-desktop.sample.json`. Refresh all of this with
43
43
  `minutework workspace sync-assets`.
44
44
 
45
+ Primitive catalog membership does not imply executability or agent exposure;
46
+ check the live-status block in skills/runtime-capability-inventory/SKILL.md and
47
+ the minutework_runtime_primitive_status workspace MCP tool before authoring
48
+ against a primitive (interim paths:
49
+ skills/runtime-primitive-interim-paths/SKILL.md).
50
+
45
51
  ## Hosted Sandbox Runtime
46
52
 
47
53
  Use `minutework sandbox create` to provision and link the workspace to its
@@ -63,6 +69,10 @@ coding agent can use them as reference: browse `skills/` and read the relevant
63
69
  automatically and `/skill-name` invokes one directly; other agents (Codex,
64
70
  Cursor) can open the files directly or ask "What skills are available?".
65
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
+
66
76
  ## Capability Gaps
67
77
 
68
78
  When a request exposes missing shared MinuteWork substrate, read
@@ -52,6 +52,7 @@ Generated-workspace-first guidance should live here, especially:
52
52
  - `workspace-guidance-refresh/SKILL.md`
53
53
  - `shell-architecture/SKILL.md`
54
54
  - `runtime-capability-inventory/SKILL.md`
55
+ - `runtime-primitive-interim-paths/SKILL.md`
55
56
  - `integration-broker-and-connectors/SKILL.md`
56
57
  - `layering-and-import-modes/SKILL.md`
57
58
  - `standalone-mobile-client/SKILL.md`
@@ -23,6 +23,8 @@ generation, itinerary generation, content generation, or structured-output UX.
23
23
  - Start with `minutework_capability_inventory` and the generated workspace
24
24
  capability guidance before assuming runtime AI capability is present,
25
25
  missing, or unsupported.
26
+ - When a needed primitive is catalogued but not yet executable or agent-exposed,
27
+ use the sanctioned interim paths in `runtime-primitive-interim-paths/SKILL.md`.
26
28
  - If runtime AI availability is unclear, inspect the linked runtime/workspace
27
29
  context or ask a clarifying question before inventing new AI infrastructure.
28
30
  - When AI drafting or generation touches external participants, guests,
@@ -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,24 +87,83 @@ 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
93
96
 
94
97
  <!-- builder-doc-sync:active-primitives:start -->
95
- - Current active primitives by family:
96
- - `records`: `records.query`, `records.upsert`
97
- - `workflow`: `workflow.run_action`, `workflow.schedule_timer`,
98
- `workflow.resume_checkpoint`, `workflow.cancel_on_thread_activity`
99
- - `projection`: `projection.publish_receipt`
100
- - `integrations`: `integrations.query_provider`,
101
- `integrations.execute_automation`
102
- - `communication`: `communication.send_email`, `communication.send_sms`
103
- - `consent`: `consent.check_channel`
104
- - `scheduling`: `scheduling.book_appointment`
105
- - `discovery`: `discovery.request_proposal`
106
- - `voice`: `voice.initiate_call`, `voice.hangup_call`,
107
- `voice.get_call_status`
108
- - `ontology`: `ontology.resolve_local`, `ontology.propose_candidate`
109
- - `command_exec`: `command_exec.run_template`
98
+ - Three-layer rule: catalogued != executor-wired != agent-exposed. Catalog membership
99
+ never implies a primitive can execute today, and an executor never implies any agent
100
+ can call it; check each layer separately.
101
+ - Default agent ring is the read-only READ_RING (`records.query`,
102
+ `app_pack.list_surfaces`, `app_pack.query`); its members need no grant. (`app_pack.*`
103
+ and `delegate_to_builder` are agent tools, not catalog primitives.) Every other tool
104
+ needs a per-agent `enable_agent_tools` grant (operator-only). Enabling the effectful
105
+ `app_pack.action` tool is additionally process-gated on the A1-A3 human-approval
106
+ surface being live for the tenant plane; surfaces with forced approval park on a human
107
+ approval before executing.
108
+ - Machine-readable copy with per-primitive live-status fields:
109
+ `skills/runtime-capability-inventory/primitive-catalog.json` (synced from the runtime
110
+ fixture). The `minutework_runtime_primitive_status` workspace MCP tool serves the same
111
+ answer, linked-runtime-backed when a runtime binding exists.
112
+ - Live executors (catalogued and wired today):
113
+ - `records.query` -- Native agent tool in the default READ_RING: enabled for the
114
+ provisioning-default agent without any grant.
115
+ - `records.upsert` -- Effectful; outside the default READ_RING, granted per agent via
116
+ enable_agent_tools (OPERATOR_RING member).
117
+ - `workflow.run_action` -- Agents reach this envelope through the app_pack.action tool
118
+ over manifest-declared agent_exposed action surfaces; approval is decided per target
119
+ capability/definition.
120
+ - `workflow.schedule_timer` -- Workflow-internal machinery (WORKFLOW_TIMER jobs); not
121
+ an agent-callable tool.
122
+ - `workflow.resume_checkpoint` -- Workflow-internal machinery driven by the jobs
123
+ worker; not an agent-callable tool.
124
+ - `workflow.cancel_on_thread_activity` -- Workflow-internal machinery; not an
125
+ agent-callable tool.
126
+ - `integrations.query_provider` -- Read-only provider query; preflight fail-closes on
127
+ connection/secret availability.
128
+ - `integrations.execute_automation` -- Approval is definition-forced in
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.
138
+ - `consent.check_channel` -- Service seam consumed by other executors and sidecars as
139
+ a preflight; not an agent-callable tool.
140
+ - `discovery.request_proposal` -- Effectful; outside the default READ_RING, granted
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.
145
+ - `command_exec.run_template` -- Operator/platform-dispatch surface; not an
146
+ agent-callable tool.
147
+ - `voice.hangup_call` -- VoiceSession finalization is live; the provider-side hangup
148
+ leg is platform-owned Phase 4. Not an agent-callable tool.
149
+ - `voice.get_call_status` -- Read-only session status lookup. Not an agent-callable
150
+ tool.
151
+ - Partial executors (wired with a deferred leg; treat the deferred
152
+ leg as unavailable):
153
+ - `scheduling.book_appointment` -- Capability is registered but the direct booking
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.
161
+ - `voice.initiate_call` -- Pre-dial stack is live (consent + TCPA preflight, approval
162
+ parking, VoiceSession lifecycle); the Twilio dial + realtime media worker are
163
+ platform-owned Phase 4.
164
+ - Catalogued-only (no executor wired; use the sanctioned interim
165
+ path):
166
+ - `projection.publish_receipt` -- Owning services emit receipts through the runtime
167
+ bridge directly (e.g. command_exec posts its own run receipts); do not build a
168
+ bespoke generic receipt executor.
110
169
  <!-- builder-doc-sync:active-primitives:end -->