@elevasis/sdk 1.36.5 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +61 -21
- package/dist/index.d.ts +93 -7
- package/dist/index.js +78 -32
- package/dist/node/index.d.ts +6 -5
- package/dist/test-utils/index.d.ts +6 -5
- package/dist/test-utils/index.js +67 -31
- package/dist/worker/index.js +7 -11
- package/package.json +4 -4
- package/reference/claude-config/sync-notes/2026-06-15-session-chat-zero-wiring.md +46 -0
- package/reference/claude-config/sync-notes/2026-06-17-agent-session-ux-features.md +34 -0
- package/reference/rules/vibe.md +1 -0
- package/reference/scaffold/recipes/extend-lead-gen.md +492 -332
- package/reference/scaffold/reference/contracts.md +14 -21
package/dist/test-utils/index.js
CHANGED
|
@@ -7561,17 +7561,13 @@ var AcqListMetadataSchema = z.object({
|
|
|
7561
7561
|
}).catchall(z.unknown());
|
|
7562
7562
|
var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100);
|
|
7563
7563
|
var ListStageCountsSchema = z.object({
|
|
7564
|
-
// Attempted counts by
|
|
7565
|
-
//
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
verified: z.number().int(),
|
|
7572
|
-
personalized: z.number().int(),
|
|
7573
|
-
uploaded: z.number().int()
|
|
7574
|
-
}),
|
|
7564
|
+
// Attempted counts keyed by the tenant's declared lead-gen stage catalog IDs.
|
|
7565
|
+
// The catalog is tenant-owned and OM-derived at compute time; the schema
|
|
7566
|
+
// validates the transport shape (string keys → integer values) rather than
|
|
7567
|
+
// a fixed key set, so tenants with custom stages receive complete telemetry.
|
|
7568
|
+
// Canonical Elevasis stages (populated, extracted, qualified, discovered,
|
|
7569
|
+
// verified, personalized, uploaded) are included when declared in the catalog.
|
|
7570
|
+
stageCounts: z.record(z.string().min(1), z.number().int()),
|
|
7575
7571
|
deliverability: z.object({
|
|
7576
7572
|
valid: z.number().int(),
|
|
7577
7573
|
risky: z.number().int(),
|
|
@@ -8775,17 +8771,48 @@ var SYSTEM_INTERFACE_PROFILES = [
|
|
|
8775
8771
|
var SYSTEM_INTERFACE_READINESS_PROFILES = SYSTEM_INTERFACE_PROFILES.map(
|
|
8776
8772
|
(profile) => profile.readinessProfile
|
|
8777
8773
|
);
|
|
8778
|
-
var SystemInterfaceReadinessProfileSchema = z.
|
|
8774
|
+
var SystemInterfaceReadinessProfileSchema = z.string().trim().min(1);
|
|
8779
8775
|
var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
|
|
8776
|
+
var SystemApiInterfaceReadinessContractSchema = z.object({
|
|
8777
|
+
/** Ontology IDs of object types the interface depends on. */
|
|
8778
|
+
requiredObjects: z.array(z.string().trim().min(1)).default([]),
|
|
8779
|
+
/** Ontology IDs of catalog types the interface requires (must be non-empty). */
|
|
8780
|
+
requiredCatalogs: z.array(z.string().trim().min(1)).default([]),
|
|
8781
|
+
/** Optional ontology kind filters (reserved for future profile extensions). */
|
|
8782
|
+
requiredKinds: z.array(z.string().trim().min(1)).optional()
|
|
8783
|
+
}).strict();
|
|
8780
8784
|
var SystemApiInterfaceSchema = z.object({
|
|
8781
8785
|
lifecycle: SystemInterfaceLifecycleSchema.default("active"),
|
|
8786
|
+
/**
|
|
8787
|
+
* Open-string profile id. Built-in platform presets are looked up through
|
|
8788
|
+
* the profile registry; custom ids are validated structurally via
|
|
8789
|
+
* `readinessContract`. Optional — `profileForInterface` provides a default.
|
|
8790
|
+
*/
|
|
8782
8791
|
readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
|
|
8783
8792
|
/**
|
|
8784
8793
|
* Resource ids that participate in this API interface. This scopes readiness
|
|
8785
8794
|
* derivation without duplicating authored required/provided contract refs.
|
|
8786
8795
|
*/
|
|
8787
|
-
resourceIds: SystemInterfaceResourceScopeSchema.optional()
|
|
8796
|
+
resourceIds: SystemInterfaceResourceScopeSchema.optional(),
|
|
8797
|
+
/**
|
|
8798
|
+
* Tenant-authorable readiness declaration. Required for custom
|
|
8799
|
+
* (non-built-in) profile ids so structural validation can proceed. Built-in
|
|
8800
|
+
* profiles ignore this field (requirements are derived from platform code).
|
|
8801
|
+
*/
|
|
8802
|
+
readinessContract: SystemApiInterfaceReadinessContractSchema.optional()
|
|
8788
8803
|
}).strict();
|
|
8804
|
+
var _profileRegistry = new Map(
|
|
8805
|
+
SYSTEM_INTERFACE_READINESS_PROFILES.map((profileId) => [
|
|
8806
|
+
profileId,
|
|
8807
|
+
{ profileId, kind: "built-in" }
|
|
8808
|
+
])
|
|
8809
|
+
);
|
|
8810
|
+
function profileForInterface(systemPath, interfaceKey, readinessProfile) {
|
|
8811
|
+
return readinessProfile ?? `${systemPath}.${interfaceKey}`;
|
|
8812
|
+
}
|
|
8813
|
+
function isBuiltInReadinessProfile(profileId) {
|
|
8814
|
+
return _profileRegistry.get(profileId)?.kind === "built-in";
|
|
8815
|
+
}
|
|
8789
8816
|
z.object({
|
|
8790
8817
|
systemPath: SystemPathSchema,
|
|
8791
8818
|
interfaceKey: SystemInterfaceKeySchema
|
|
@@ -9032,14 +9059,11 @@ function addReadinessIssue(issues, family, code, message, details = {}) {
|
|
|
9032
9059
|
function formatInterfaceIdentity(systemPath, interfaceKey) {
|
|
9033
9060
|
return `${systemPath}/${interfaceKey}`;
|
|
9034
9061
|
}
|
|
9035
|
-
function profileForInterface(systemPath, interfaceKey, readinessProfile) {
|
|
9036
|
-
return readinessProfile ?? `${systemPath}.${interfaceKey}`;
|
|
9037
|
-
}
|
|
9038
9062
|
function readinessMarkerPath(context) {
|
|
9039
9063
|
return context.interfaceKey === "api" ? `systems.${context.systemPath}.apiInterface` : `systems.${context.systemPath}.derivedCrmHandoffReadiness`;
|
|
9040
9064
|
}
|
|
9041
9065
|
function formatSupportedReadinessProfiles() {
|
|
9042
|
-
return
|
|
9066
|
+
return SYSTEM_INTERFACE_PROFILES.map((p3) => `"${p3.readinessProfile}"`).join(", ");
|
|
9043
9067
|
}
|
|
9044
9068
|
function getActiveScopedResources(model, resourceIds, issues, context) {
|
|
9045
9069
|
const resources = [];
|
|
@@ -9231,9 +9255,6 @@ function getLeadGenCrmHandoffResourceIds(model) {
|
|
|
9231
9255
|
function getSystemInterfaceReadinessMarker(model, request) {
|
|
9232
9256
|
const system = getSystem(model, request.systemPath);
|
|
9233
9257
|
if (system === void 0) return void 0;
|
|
9234
|
-
if (request.interfaceKey === LEAD_GEN_API_INTERFACE.interfaceKey) {
|
|
9235
|
-
return system.apiInterface;
|
|
9236
|
-
}
|
|
9237
9258
|
if (request.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && request.interfaceKey === LEAD_GEN_CRM_HANDOFF_INTERFACE.interfaceKey) {
|
|
9238
9259
|
return {
|
|
9239
9260
|
lifecycle: "active",
|
|
@@ -9241,6 +9262,9 @@ function getSystemInterfaceReadinessMarker(model, request) {
|
|
|
9241
9262
|
resourceIds: getLeadGenCrmHandoffResourceIds(model)
|
|
9242
9263
|
};
|
|
9243
9264
|
}
|
|
9265
|
+
if (request.interfaceKey === "api" && system.apiInterface !== void 0) {
|
|
9266
|
+
return system.apiInterface;
|
|
9267
|
+
}
|
|
9244
9268
|
return void 0;
|
|
9245
9269
|
}
|
|
9246
9270
|
function mergeLeadGenDerivedCatalogs(model) {
|
|
@@ -9285,6 +9309,18 @@ function tryCompileBusinessOntology(model, readinessProfile, issues) {
|
|
|
9285
9309
|
return void 0;
|
|
9286
9310
|
}
|
|
9287
9311
|
}
|
|
9312
|
+
function requireContractReadiness(issues, index2, resources, contract, context) {
|
|
9313
|
+
const reads = resourceBindingIds(resources, "reads");
|
|
9314
|
+
const catalogs = resourceBindingIds(resources, "usesCatalogs");
|
|
9315
|
+
for (const objectId of contract.requiredObjects) {
|
|
9316
|
+
requireObjectReadiness(issues, index2, objectId, context);
|
|
9317
|
+
requireScopedBinding(issues, reads, "reads", objectId, context);
|
|
9318
|
+
}
|
|
9319
|
+
for (const catalogId of contract.requiredCatalogs) {
|
|
9320
|
+
requireCatalogReadiness(issues, index2, catalogId, context);
|
|
9321
|
+
requireScopedBinding(issues, catalogs, "usesCatalogs", catalogId, context);
|
|
9322
|
+
}
|
|
9323
|
+
}
|
|
9288
9324
|
function computeInterfaceReadiness(model, request) {
|
|
9289
9325
|
const issues = [];
|
|
9290
9326
|
const system = getSystem(model, request.systemPath);
|
|
@@ -9332,20 +9368,22 @@ function computeInterfaceReadiness(model, request) {
|
|
|
9332
9368
|
{ path: `${readinessMarkerPath(request)}.lifecycle` }
|
|
9333
9369
|
);
|
|
9334
9370
|
}
|
|
9335
|
-
const
|
|
9336
|
-
|
|
9371
|
+
const checkedReadinessProfile = readinessProfile ?? profileForInterface(request.systemPath, request.interfaceKey);
|
|
9372
|
+
const isBuiltIn = isBuiltInReadinessProfile(checkedReadinessProfile);
|
|
9373
|
+
const readinessContract = systemInterface.readinessContract;
|
|
9374
|
+
if (!isBuiltIn && readinessContract === void 0) {
|
|
9337
9375
|
addReadinessIssue(
|
|
9338
9376
|
issues,
|
|
9339
9377
|
"SYSTEM_INTERFACE_INVALID",
|
|
9340
|
-
"
|
|
9341
|
-
`System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}"
|
|
9342
|
-
{ path: `${readinessMarkerPath(request)}.
|
|
9378
|
+
"missing-readiness-contract",
|
|
9379
|
+
`System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" uses custom readiness profile "${checkedReadinessProfile}" but declares no readinessContract. Built-in profiles: ${formatSupportedReadinessProfiles()}.`,
|
|
9380
|
+
{ path: `${readinessMarkerPath(request)}.readinessContract`, ref: checkedReadinessProfile }
|
|
9343
9381
|
);
|
|
9344
9382
|
return {
|
|
9345
9383
|
ready: false,
|
|
9346
9384
|
systemPath: request.systemPath,
|
|
9347
9385
|
interfaceKey: request.interfaceKey,
|
|
9348
|
-
readinessProfile,
|
|
9386
|
+
readinessProfile: checkedReadinessProfile,
|
|
9349
9387
|
scopedResourceIds,
|
|
9350
9388
|
issues
|
|
9351
9389
|
};
|
|
@@ -9359,10 +9397,6 @@ function computeInterfaceReadiness(model, request) {
|
|
|
9359
9397
|
{ path: `${readinessMarkerPath(request)}.resourceIds` }
|
|
9360
9398
|
);
|
|
9361
9399
|
}
|
|
9362
|
-
const checkedReadinessProfile = readinessProfile;
|
|
9363
|
-
if (checkedReadinessProfile === void 0) {
|
|
9364
|
-
throw new Error("Supported readiness profile unexpectedly resolved to undefined");
|
|
9365
|
-
}
|
|
9366
9400
|
const resources = getActiveScopedResources(model, scopedResourceIds, issues, request);
|
|
9367
9401
|
const index2 = tryCompileBusinessOntology(model, checkedReadinessProfile, issues);
|
|
9368
9402
|
if (index2 !== void 0) {
|
|
@@ -9374,13 +9408,15 @@ function computeInterfaceReadiness(model, request) {
|
|
|
9374
9408
|
requireLeadGenInterfaceReadiness(issues, index2, resources, request);
|
|
9375
9409
|
requireCrmInterfaceReadiness(issues, index2, resources, { ...request, allowForeignOwner: true });
|
|
9376
9410
|
requireHandoffBridgeReadiness(issues, model, request);
|
|
9411
|
+
} else if (readinessContract !== void 0) {
|
|
9412
|
+
requireContractReadiness(issues, index2, resources, readinessContract, request);
|
|
9377
9413
|
}
|
|
9378
9414
|
}
|
|
9379
9415
|
return {
|
|
9380
9416
|
ready: issues.length === 0,
|
|
9381
9417
|
systemPath: request.systemPath,
|
|
9382
9418
|
interfaceKey: request.interfaceKey,
|
|
9383
|
-
readinessProfile,
|
|
9419
|
+
readinessProfile: checkedReadinessProfile,
|
|
9384
9420
|
scopedResourceIds,
|
|
9385
9421
|
issues
|
|
9386
9422
|
};
|
package/dist/worker/index.js
CHANGED
|
@@ -5537,17 +5537,13 @@ var AcqListMetadataSchema = z.object({
|
|
|
5537
5537
|
}).catchall(z.unknown());
|
|
5538
5538
|
var ProspectingBuildTemplateIdSchema = z.string().trim().min(1).max(100);
|
|
5539
5539
|
var ListStageCountsSchema = z.object({
|
|
5540
|
-
// Attempted counts by
|
|
5541
|
-
//
|
|
5542
|
-
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
verified: z.number().int(),
|
|
5548
|
-
personalized: z.number().int(),
|
|
5549
|
-
uploaded: z.number().int()
|
|
5550
|
-
}),
|
|
5540
|
+
// Attempted counts keyed by the tenant's declared lead-gen stage catalog IDs.
|
|
5541
|
+
// The catalog is tenant-owned and OM-derived at compute time; the schema
|
|
5542
|
+
// validates the transport shape (string keys → integer values) rather than
|
|
5543
|
+
// a fixed key set, so tenants with custom stages receive complete telemetry.
|
|
5544
|
+
// Canonical Elevasis stages (populated, extracted, qualified, discovered,
|
|
5545
|
+
// verified, personalized, uploaded) are included when declared in the catalog.
|
|
5546
|
+
stageCounts: z.record(z.string().min(1), z.number().int()),
|
|
5551
5547
|
deliverability: z.object({
|
|
5552
5548
|
valid: z.number().int(),
|
|
5553
5549
|
risky: z.number().int(),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elevasis/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.0",
|
|
4
4
|
"description": "SDK for building Elevasis organization resources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"tsup": "^8.0.0",
|
|
59
59
|
"typescript": "5.9.2",
|
|
60
60
|
"zod": "^4.1.0",
|
|
61
|
-
"@repo/core": "0.
|
|
62
|
-
"@repo/
|
|
63
|
-
"@repo/
|
|
61
|
+
"@repo/core": "0.53.0",
|
|
62
|
+
"@repo/eslint-config": "0.0.0",
|
|
63
|
+
"@repo/typescript-config": "0.0.0"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"lint": "eslint src --max-warnings 0",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Session Chat Zero-Wiring Default Slot
|
|
2
|
+
|
|
3
|
+
## Why this note exists
|
|
4
|
+
|
|
5
|
+
`@elevasis/ui` (>= 2.56.0) makes `SessionChatPage`'s `renderConversationView` slot
|
|
6
|
+
optional and self-defaulting: when omitted, the page renders the shared
|
|
7
|
+
`SessionConversationView` itself, resolving `apiUrl` from the service context
|
|
8
|
+
(now exposed on `ElevasisServiceContextValue`). The template `SessionChatPage`
|
|
9
|
+
now mounts the shared page with NO slot, and the orphan null-stub
|
|
10
|
+
`ui/src/features/assistant/components/ConversationView.tsx` is deleted. Projects
|
|
11
|
+
that omit the slot get a working session chat out of the box; customization stays
|
|
12
|
+
opt-in via the same prop. Backward-compatible: hosts that still pass the slot are
|
|
13
|
+
unaffected.
|
|
14
|
+
|
|
15
|
+
## Applies to
|
|
16
|
+
|
|
17
|
+
- All template-derived projects with the agent-sessions page
|
|
18
|
+
(`ui/src/features/operations/sessions/SessionChatPage.tsx`).
|
|
19
|
+
- Any project still wiring a local `ConversationView` stub
|
|
20
|
+
(`ui/src/features/assistant/components/ConversationView.tsx`) -> these render
|
|
21
|
+
a blank chat with a stuck `DISCONNECTED` badge until reconciled.
|
|
22
|
+
|
|
23
|
+
## Required actions
|
|
24
|
+
|
|
25
|
+
- Bump `@elevasis/ui` to `^2.56.0` (or later) and install. (The ship train's
|
|
26
|
+
`external-sync` stage does this automatically via the package-cascade baseline;
|
|
27
|
+
manual `pnpm update` is not required.)
|
|
28
|
+
- Drop the explicit `renderConversationView={...}` slot from your
|
|
29
|
+
`SessionChatPage.tsx` and remove the local stub import, relying on the new
|
|
30
|
+
default. (To keep a custom body, keep passing the slot.)
|
|
31
|
+
- Delete the now-unused local null-stub
|
|
32
|
+
`ui/src/features/assistant/components/ConversationView.tsx`.
|
|
33
|
+
|
|
34
|
+
## Verification
|
|
35
|
+
|
|
36
|
+
- `pnpm -C ui check-types` passes against `@elevasis/ui@^2.56.0`.
|
|
37
|
+
- The session-detail chat page (`/operations/sessions/$sessionId`) renders
|
|
38
|
+
history + live messages and the `DISCONNECTED` badge clears, with NO slot wired.
|
|
39
|
+
|
|
40
|
+
## Not handled by /git-sync
|
|
41
|
+
|
|
42
|
+
- `/git-sync` surfaces this note and pulls the template `SessionChatPage`
|
|
43
|
+
baseline, but the diverged tenant copy is preserved (merge-managed) -- you must
|
|
44
|
+
manually drop the explicit slot.
|
|
45
|
+
- `/git-sync` does NOT delete the local `ConversationView` stub
|
|
46
|
+
(`delete_policy: none`); remove it manually.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Agent session UX features (End Conversation, intake form, session naming)
|
|
2
|
+
|
|
3
|
+
## Why this note exists
|
|
4
|
+
|
|
5
|
+
This train bumps `@elevasis/core` and `@elevasis/ui` with three tenant-facing agent-session features that ship entirely inside the published packages (no template source edit, package-cascade-only):
|
|
6
|
+
|
|
7
|
+
- **End Conversation** (`@elevasis/ui`) — both the internal Agent Sessions surface (`features/operations/sessions/SessionDetailsPanel`) and the public agent-chat surface (`features/public-agent-chat/PublicAgentChat`) now render an "End conversation" control. Ending preserves history and blocks new turns (distinct from Delete, which removes). The public composer locks out after end with a "This conversation has ended" placeholder.
|
|
8
|
+
- **Welcome intake form** (`@elevasis/ui` + `@elevasis/core`) — the public chat intro screen renders an optional intake form driven by the grant's `capture_fields` column (now typed as `CaptureField[]` in `@elevasis/core`'s public-agent-chat schema). Collected values flow into `session.metadata`. All fields are optional.
|
|
9
|
+
- **Session naming from intake** (`@elevasis/ui` + platform API) — sessions are titled from the collected `name` (server-side, with a first-user-message fallback), and the Agent Sessions list now renders `session.title` as the row label.
|
|
10
|
+
|
|
11
|
+
The session `session:end` / `session:ended` WebSocket messages, the internal `POST /sessions/:id/end` route, and server-side title derivation live in the Elevasis-deployed platform API — tenants receive that behavior automatically; the package bump only delivers the frontend.
|
|
12
|
+
|
|
13
|
+
## Applies to
|
|
14
|
+
|
|
15
|
+
- All template-derived projects that expose the Agent Sessions page (`ui/src/features/operations/sessions/`) or the public agent-chat surface (`ui/src/features/public-agent-chat/`).
|
|
16
|
+
- Projects that configure public agent grants and want to collect intake fields (Name plus arbitrary configurable fields) on the public intro screen.
|
|
17
|
+
|
|
18
|
+
## Required actions
|
|
19
|
+
|
|
20
|
+
- Bump `@elevasis/core` to `^0.52.0` and `@elevasis/ui` to `^2.59.0` (or later) and install. The ship train's `external-sync` stage does this automatically via the package-cascade baselines — manual `pnpm update` is not required.
|
|
21
|
+
- No source changes are required to receive End Conversation, the intake form, or title-in-list — they ship inside `@elevasis/ui` / `@elevasis/core`.
|
|
22
|
+
- To enable an intake form on a public agent, populate the grant's `capture_fields` (array of `{ key, label, type?, required? }`). There is no Command Center editor for `capture_fields` yet — configure it via a grant write. Leaving `capture_fields` empty renders the intro exactly as before (no form).
|
|
23
|
+
|
|
24
|
+
## Verification
|
|
25
|
+
|
|
26
|
+
- `pnpm -C ui check-types` passes against `@elevasis/ui@^2.59.0`.
|
|
27
|
+
- Open the public agent chat for a grant with `capture_fields` set → the intro renders the configured fields; entering a name and starting the session titles the session by that name in the Agent Sessions list.
|
|
28
|
+
- With no `capture_fields` → the intro renders unchanged; the session is titled from the first user message.
|
|
29
|
+
- Click "End conversation" on either the public header or the internal session detail panel → the session ends, history is preserved, and a new turn is rejected ("Session has ended").
|
|
30
|
+
|
|
31
|
+
## Not handled by /git-sync
|
|
32
|
+
|
|
33
|
+
- `/git-sync` surfaces this note and pulls the propagated package baselines, but it does not run the `@elevasis/core` / `@elevasis/ui` install for you when reconciling manually outside the ship train.
|
|
34
|
+
- The intake/title and End features depend on the Elevasis-deployed platform API (`session:end` handling, `/sessions/:id/end`, server-side title derivation). They are not part of a tenant's own backend and require no tenant action — but they only work once the platform API carrying them is deployed.
|
package/reference/rules/vibe.md
CHANGED
|
@@ -270,3 +270,4 @@ Layers 2 (Public API), 3 (UI Shell Runtime), 5 (Toolkit), and 6 (Graph) require
|
|
|
270
270
|
- Vibe is not a skill. It lives in this rule file + CLAUDE.md + the PreToolUse hook -- not in `.claude/skills/`.
|
|
271
271
|
- Vibe does not own the codify ceremony. `/om` owns draft, confirm, write, and typecheck for both Level A and Level B codify pipelines (decision #21 -- Codify ceremony delegated to `/om`). Vibe detects intent and hands off.
|
|
272
272
|
- Vibe is not active in the monorepo. If working inside the monorepo (not an `external/` project), this ambient routing does not apply.
|
|
273
|
+
- Vibe does not flip **public agent exposure**. Making a deployed agent reachable on the public internet (the `agent_access_grants` row behind `/public/agents/:slug`, managed via `grant:create` / `grant:update` / `grant:disable` or the Resource-page public/private toggle) is a **security boundary deliberately kept out of ambient routing** — a non-technical user describing their business must never be able to expose an agent by accident. This is a deliberate non-route, not an unhandled gap: do NOT classify "make my agent public" / "put the interview online" as Toggle (which is System on/off) and do NOT auto-execute. Surface the `grant:*` CLI or the Resource-page toggle in plain language and require explicit confirmation.
|