@elevasis/sdk 1.15.1 → 1.16.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 +2325 -124
- package/dist/index.d.ts +410 -473
- package/dist/index.js +96 -44
- package/dist/node/index.d.ts +69 -0
- package/dist/node/index.js +273 -0
- package/dist/test-utils/index.d.ts +473 -466
- package/dist/types/worker/platform.d.ts +2 -9
- package/package.json +12 -3
- package/reference/_navigation.md +23 -1
- package/reference/_reference-manifest.json +98 -0
- package/reference/claude-config/rules/agent-start-here.md +13 -0
- package/reference/claude-config/rules/organization-model.md +40 -40
- package/reference/claude-config/rules/organization-os.md +16 -16
- package/reference/claude-config/rules/vibe.md +13 -13
- package/reference/claude-config/skills/knowledge/SKILL.md +253 -0
- package/reference/claude-config/skills/{configure → knowledge}/operations/codify-level-a.md +100 -100
- package/reference/claude-config/skills/{configure → knowledge}/operations/codify-level-b.md +158 -158
- package/reference/claude-config/skills/knowledge/operations/customers.md +109 -0
- package/reference/claude-config/skills/knowledge/operations/features.md +113 -0
- package/reference/claude-config/skills/knowledge/operations/goals.md +118 -0
- package/reference/claude-config/skills/knowledge/operations/identity.md +93 -0
- package/reference/claude-config/skills/knowledge/operations/labels.md +89 -0
- package/reference/claude-config/skills/knowledge/operations/offerings.md +109 -0
- package/reference/claude-config/skills/knowledge/operations/roles.md +99 -0
- package/reference/claude-config/skills/knowledge/operations/techStack.md +102 -0
- package/reference/claude-config/skills/run-ui/SKILL.md +73 -0
- package/reference/claude-config/skills/setup/SKILL.md +270 -270
- package/reference/claude-config/skills/tutorial/SKILL.md +249 -0
- package/reference/claude-config/skills/tutorial/progress-template.md +74 -0
- package/reference/claude-config/skills/tutorial/technical.md +1309 -0
- package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -0
- package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +71 -0
- package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +59 -0
- package/reference/deployment/index.mdx +5 -5
- package/reference/examples/organization-model.ts +40 -0
- package/reference/framework/index.mdx +1 -1
- package/reference/framework/tutorial-system.mdx +86 -173
- package/reference/packages/core/src/knowledge/README.md +32 -0
- package/reference/packages/ui/src/knowledge/README.md +31 -0
- package/reference/packages/ui/src/theme/presets/README.md +19 -0
- package/reference/scaffold/core/organization-model.mdx +1 -1
- package/reference/scaffold/recipes/add-a-feature.md +1 -1
- package/reference/scaffold/recipes/customize-crm-actions.md +433 -433
- package/reference/scaffold/recipes/customize-organization-model.md +3 -3
- package/reference/scaffold/recipes/extend-lead-gen.md +90 -55
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +1 -1
- package/reference/scaffold/recipes/index.md +6 -0
- package/reference/scaffold/reference/contracts.md +1265 -1154
- package/reference/scaffold/reference/feature-registry.md +2 -1
- package/reference/scaffold/ui/composition-extensibility.mdx +17 -0
- package/reference/claude-config/skills/configure/SKILL.md +0 -98
- package/reference/claude-config/skills/configure/operations/customers.md +0 -150
- package/reference/claude-config/skills/configure/operations/features.md +0 -162
- package/reference/claude-config/skills/configure/operations/goals.md +0 -147
- package/reference/claude-config/skills/configure/operations/identity.md +0 -133
- package/reference/claude-config/skills/configure/operations/labels.md +0 -128
- package/reference/claude-config/skills/configure/operations/offerings.md +0 -159
- package/reference/claude-config/skills/configure/operations/roles.md +0 -153
- package/reference/claude-config/skills/configure/operations/techStack.md +0 -139
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# Identity domain
|
|
2
|
+
|
|
3
|
+
The `identity` domain captures the organization's legal identity, purpose, and operational anchors.
|
|
4
|
+
It is distinct from `branding` (display identity: logos, product names) — editing identity fields
|
|
5
|
+
here does not touch any visual or branding configuration.
|
|
6
|
+
|
|
7
|
+
## Schema
|
|
8
|
+
|
|
9
|
+
Source: `packages/core/src/organization-model/domains/identity.ts`
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
IdentityDomainSchema = z.object({
|
|
13
|
+
mission: z.string().trim().max(1000).default(''),
|
|
14
|
+
vision: z.string().trim().max(1000).default(''),
|
|
15
|
+
legalName: z.string().trim().max(200).default(''),
|
|
16
|
+
entityType: z.string().trim().max(100).default(''), // e.g. "LLC", "Corporation"
|
|
17
|
+
jurisdiction: z.string().trim().max(200).default(''), // e.g. "United States – Delaware"
|
|
18
|
+
industryCategory: z.string().trim().max(200).default(''), // e.g. "Marketing Agency"
|
|
19
|
+
geographicFocus: z.string().trim().max(200).default(''), // e.g. "North America"
|
|
20
|
+
timeZone: z.string().trim().max(100).default('UTC'), // IANA identifier
|
|
21
|
+
businessHours: BusinessHoursSchema // per-day { open, close } in HH:MM
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`BusinessHoursSchema` is an object with optional keys `monday` through `sunday`, each holding
|
|
26
|
+
`{ open: "HH:MM", close: "HH:MM" }`. An empty object `{}` means not configured.
|
|
27
|
+
|
|
28
|
+
## Field reference
|
|
29
|
+
|
|
30
|
+
| Field | Type | Max | Notes |
|
|
31
|
+
| ------------------ | ------ | ---- | -------------------------------------------------------- |
|
|
32
|
+
| `mission` | string | 1000 | Why the organization exists |
|
|
33
|
+
| `vision` | string | 1000 | Where the organization is headed long-term |
|
|
34
|
+
| `legalName` | string | 200 | Registered legal name |
|
|
35
|
+
| `entityType` | string | 100 | e.g. "LLC", "Corporation", "Sole Proprietor" |
|
|
36
|
+
| `jurisdiction` | string | 200 | e.g. "United States – Delaware", "Canada – Ontario" |
|
|
37
|
+
| `industryCategory` | string | 200 | e.g. "Marketing Agency", "SaaS", "Professional Services" |
|
|
38
|
+
| `geographicFocus` | string | 200 | e.g. "North America", "Global", "Southeast Asia" |
|
|
39
|
+
| `timeZone` | string | 100 | IANA identifier, e.g. `America/Los_Angeles` |
|
|
40
|
+
| `businessHours` | object | -- | Per-day `{ open: "HH:MM", close: "HH:MM" }` |
|
|
41
|
+
|
|
42
|
+
## Validation rules
|
|
43
|
+
|
|
44
|
+
- All string fields default to empty string `''`; none are required to be non-empty at schema level
|
|
45
|
+
- `timeZone` defaults to `"UTC"` when not set; agents should treat a value of `"UTC"` as
|
|
46
|
+
potentially unconfigured and surface it for review
|
|
47
|
+
- `businessHours` defaults to `{}` (not configured); an empty object is valid
|
|
48
|
+
- Per-day entries must follow `"HH:MM"` 24-hour format; the schema does not enforce range bounds
|
|
49
|
+
but convention is `00:00`–`23:59`
|
|
50
|
+
- `jurisdiction` should use the format `"Country – Region"` (em dash, not hyphen) for
|
|
51
|
+
consistency across agents that parse it
|
|
52
|
+
|
|
53
|
+
## Examples
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
identity: {
|
|
57
|
+
mission: "We help SMBs automate complex operations using AI.",
|
|
58
|
+
vision: "A world where every business operates at the efficiency of a Fortune 500.",
|
|
59
|
+
legalName: "Acme Operations LLC",
|
|
60
|
+
entityType: "LLC",
|
|
61
|
+
jurisdiction: "United States – Delaware",
|
|
62
|
+
industryCategory: "AI Automation / Professional Services",
|
|
63
|
+
geographicFocus: "North America",
|
|
64
|
+
timeZone: "America/Chicago",
|
|
65
|
+
businessHours: {
|
|
66
|
+
monday: { open: "09:00", close: "17:00" },
|
|
67
|
+
tuesday: { open: "09:00", close: "17:00" },
|
|
68
|
+
wednesday: { open: "09:00", close: "17:00" },
|
|
69
|
+
thursday: { open: "09:00", close: "17:00" },
|
|
70
|
+
friday: { open: "09:00", close: "17:00" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Where it lives in the adapter
|
|
76
|
+
|
|
77
|
+
`foundations/config/organization-model.ts` under the `identity` key of
|
|
78
|
+
`defineOrganizationModel({...})`.
|
|
79
|
+
|
|
80
|
+
To read the current values: open the adapter file and inspect the `identity` block directly, or
|
|
81
|
+
use `pnpm exec elevasis-sdk knowledge:cat identity` (external project).
|
|
82
|
+
|
|
83
|
+
## Write path
|
|
84
|
+
|
|
85
|
+
To edit any field, the `/knowledge` skill runs the codify ceremony
|
|
86
|
+
(`operations/codify-level-a.md`): snapshot → propose → confirm → write → typecheck → Zod parse →
|
|
87
|
+
rollback on failure. Only the confirmed fields are written; no other top-level keys in the adapter
|
|
88
|
+
are touched.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
**Read via `/knowledge`** — natural-language queries like "what's our identity set to?" or
|
|
93
|
+
"what timezone are we in?" route to this domain via the skill's intent classifier.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Labels domain
|
|
2
|
+
|
|
3
|
+
`label` is an inline display field carried by status entries, stage entries, feature entries, and
|
|
4
|
+
navigation surfaces in the OrganizationModel. Labels control what users see in the UI and what
|
|
5
|
+
agents say when narrating state. Editing a label does not change the entry's `id` or
|
|
6
|
+
`semanticClass` -- only the human-readable display string. This is Level A only (config-only
|
|
7
|
+
edits to `core/config/organization-model.ts`).
|
|
8
|
+
|
|
9
|
+
## What carries labels
|
|
10
|
+
|
|
11
|
+
The following model elements have editable inline `label` fields:
|
|
12
|
+
|
|
13
|
+
**Status / stage entries.** Each domain that carries an enum-like array exposes per-entry labels:
|
|
14
|
+
|
|
15
|
+
- `sales.statuses` -- deal pipeline stages.
|
|
16
|
+
- `prospecting.statuses` -- lead lifecycle stages.
|
|
17
|
+
- `projects.statuses` -- project and task stages.
|
|
18
|
+
|
|
19
|
+
Source of platform defaults: `packages/core/src/organization-model/domains/{sales,prospecting,projects}.ts`.
|
|
20
|
+
|
|
21
|
+
Each status entry shape:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
{ id: 'new', label: 'New Lead', semanticClass: 'active', color: 'blue' }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Features.** The `label` field on a feature entry. Editing it changes sidebar nav text and any
|
|
28
|
+
agent narration that references the feature by label.
|
|
29
|
+
|
|
30
|
+
**Navigation surfaces.** Surface entries in the `navigation.surfaces` array each carry a `label`.
|
|
31
|
+
Editing changes breadcrumb text and nav item display.
|
|
32
|
+
|
|
33
|
+
## What is NOT in scope
|
|
34
|
+
|
|
35
|
+
`id` and `semanticClass` of any entry must never change in a label edit -- they are structural
|
|
36
|
+
anchors used by code, hooks, and workflow adapters. Only `label` (and optionally `color` or
|
|
37
|
+
`icon`) are in scope. To rename an `id`, escalate to a separate Level B refactor with explicit
|
|
38
|
+
confirmation, because every consumer that references the old `id` must be updated in the same
|
|
39
|
+
change.
|
|
40
|
+
|
|
41
|
+
## Validation rules
|
|
42
|
+
|
|
43
|
+
- `label` is non-empty, max 120 characters.
|
|
44
|
+
- `id` and `semanticClass` are unchanged from the previous state.
|
|
45
|
+
- Entries not being edited remain byte-identical in the output -- partial array rewrites are
|
|
46
|
+
preferred over wholesale array replacement to minimize diff surface.
|
|
47
|
+
|
|
48
|
+
## Realistic examples
|
|
49
|
+
|
|
50
|
+
Rename two sales statuses:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Domain: sales (deal pipeline)
|
|
54
|
+
new: "New Lead" -> "Inbound Lead"
|
|
55
|
+
proposal: "Proposal Sent" -> "Proposal Out"
|
|
56
|
+
negotiation: (unchanged)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Rename a feature label without changing its ID:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
features:
|
|
63
|
+
crm: label "CRM" -> "Sales Pipeline"
|
|
64
|
+
(id stays 'crm'; CRM_FEATURE_ID constant unchanged)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Rename a navigation surface:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
navigation.surfaces:
|
|
71
|
+
crm-pipeline: label "Pipeline" -> "Deal Pipeline"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Validation gate
|
|
75
|
+
|
|
76
|
+
Every label change must pass before codify completes:
|
|
77
|
+
|
|
78
|
+
1. `pnpm -C operations check-types`.
|
|
79
|
+
2. `resolveOrganizationModel()` and `OrganizationModelSchema.parse()` succeed on the merged result.
|
|
80
|
+
|
|
81
|
+
On failure, the codify ceremony rolls back. See `operations/codify-level-a.md` for the rollback
|
|
82
|
+
procedure.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
> **Read via `/knowledge`** -- natural-language queries like "what's the label for the proposal
|
|
87
|
+
> stage?" or "what do we call the SEO feature?" route to this domain via the skill's intent
|
|
88
|
+
> classifier. To rename one or more labels, the `/knowledge` skill triggers the codify ceremony
|
|
89
|
+
> when intent classifies as Codify.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Offerings domain
|
|
2
|
+
|
|
3
|
+
The `offerings` domain describes what the organization sells or delivers — a catalog of products
|
|
4
|
+
and services modeled after the Business Model Canvas "Value Propositions". Agents use offerings
|
|
5
|
+
for quoting, proposal generation, and scope-of-work reasoning.
|
|
6
|
+
|
|
7
|
+
## Schema
|
|
8
|
+
|
|
9
|
+
Source: `packages/core/src/organization-model/domains/offerings.ts`
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
OfferingsDomainSchema = z.object({
|
|
13
|
+
products: z.array(ProductSchema).default([])
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
ProductSchema = z.object({
|
|
17
|
+
id: z.string().trim().min(1).max(100), // stable ID, e.g. "product-starter-plan"
|
|
18
|
+
name: z.string().trim().max(200).default(''), // display name
|
|
19
|
+
description: z.string().trim().max(2000).default(''), // what it delivers
|
|
20
|
+
pricingModel: PricingModelSchema.default('custom'), // 'one-time' | 'subscription' | 'usage-based' | 'custom'
|
|
21
|
+
price: z.number().min(0).default(0), // base price amount (>= 0)
|
|
22
|
+
currency: z.string().trim().max(10).default('USD'),// ISO 4217, e.g. "USD", "EUR"
|
|
23
|
+
targetSegmentIds: z.array(z.string()).default([]), // must ref customers.segments[].id
|
|
24
|
+
deliveryFeatureId: z.string().optional() // optional ref to features[].id
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`pricingModel` values:
|
|
29
|
+
|
|
30
|
+
- `one-time` -- single purchase (setup fee, project fee)
|
|
31
|
+
- `subscription` -- recurring (monthly/annual SaaS, retainer)
|
|
32
|
+
- `usage-based` -- metered by consumption (API calls, seats)
|
|
33
|
+
- `custom` -- negotiated or bespoke pricing
|
|
34
|
+
|
|
35
|
+
## Field reference
|
|
36
|
+
|
|
37
|
+
| Field | Type | Max | Notes |
|
|
38
|
+
| ------------------- | -------- | ---- | -------------------------------------------------------- |
|
|
39
|
+
| `id` | string | 100 | Stable key, min 1 char; e.g. `"product-starter-plan"` |
|
|
40
|
+
| `name` | string | 200 | Display name |
|
|
41
|
+
| `description` | string | 2000 | What this product or service delivers |
|
|
42
|
+
| `pricingModel` | enum | -- | `one-time`, `subscription`, `usage-based`, or `custom` |
|
|
43
|
+
| `price` | number | -- | Base price amount, min 0; use 0 for fully custom pricing |
|
|
44
|
+
| `currency` | string | 10 | ISO 4217 code; defaults to `"USD"` |
|
|
45
|
+
| `targetSegmentIds` | string[] | -- | Each entry must reference a `customers.segments[].id` |
|
|
46
|
+
| `deliveryFeatureId` | string | -- | Optional reference to a `features[].id` |
|
|
47
|
+
|
|
48
|
+
## Validation rules
|
|
49
|
+
|
|
50
|
+
- `id` is the stable key; changing it after creation is a breaking change for any downstream
|
|
51
|
+
references
|
|
52
|
+
- `targetSegmentIds` entries must exist in `customers.segments[].id`; the schema enforces this
|
|
53
|
+
at parse time — missing references cause `resolveOrganizationModel()` to fail
|
|
54
|
+
- `deliveryFeatureId` (when present) must exist in `features[].id`; same parse-time enforcement
|
|
55
|
+
- `price` must be >= 0; use 0 when pricing is fully custom or not yet set
|
|
56
|
+
- `currency` must be a valid ISO 4217 code by convention (the schema only validates length)
|
|
57
|
+
- Cross-reference: if a product is removed, surface any `targetSegmentIds` in other products
|
|
58
|
+
that reference the removed ID
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
offerings: {
|
|
64
|
+
products: [
|
|
65
|
+
{
|
|
66
|
+
id: "product-full-service-retainer",
|
|
67
|
+
name: "Full-Service Retainer",
|
|
68
|
+
description: "End-to-end campaign delivery, reporting, and optimization for SMB clients.",
|
|
69
|
+
pricingModel: "subscription",
|
|
70
|
+
price: 2500,
|
|
71
|
+
currency: "USD",
|
|
72
|
+
targetSegmentIds: ["segment-smb-agencies"],
|
|
73
|
+
deliveryFeatureId: undefined
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "product-one-time-audit",
|
|
77
|
+
name: "One-Time Operations Audit",
|
|
78
|
+
description: "Single-engagement review of current workflows with a remediation roadmap.",
|
|
79
|
+
pricingModel: "one-time",
|
|
80
|
+
price: 1500,
|
|
81
|
+
currency: "USD",
|
|
82
|
+
targetSegmentIds: ["segment-smb-agencies"],
|
|
83
|
+
deliveryFeatureId: undefined
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Where it lives in the adapter
|
|
90
|
+
|
|
91
|
+
`foundations/config/organization-model.ts` under the `offerings` key of
|
|
92
|
+
`defineOrganizationModel({...})`.
|
|
93
|
+
|
|
94
|
+
To read current products: open the adapter file and inspect the `offerings.products` array, or
|
|
95
|
+
use `pnpm exec elevasis-sdk knowledge:cat offerings` (external project).
|
|
96
|
+
|
|
97
|
+
## Write path
|
|
98
|
+
|
|
99
|
+
To add, edit, or remove a product, the `/knowledge` skill runs the codify ceremony
|
|
100
|
+
(`operations/codify-level-a.md`): snapshot → propose → confirm → write → typecheck → Zod parse →
|
|
101
|
+
rollback on failure. Only the `products` array is written; no other keys in the adapter are
|
|
102
|
+
touched. Before writing, the skill verifies all `targetSegmentIds` and `deliveryFeatureId`
|
|
103
|
+
references resolve. When adding, append to the array. When editing, replace by `id`. When
|
|
104
|
+
removing, filter out — and surface any dangling references first.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
**Read via `/knowledge`** — natural-language queries like "what do we sell?" or "what's the
|
|
109
|
+
pricing on the retainer?" route to this domain via the skill's intent classifier.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Roles domain
|
|
2
|
+
|
|
3
|
+
The `roles` domain describes who does what inside the organization — a role chart inspired by the
|
|
4
|
+
EOS Accountability Chart but using plain-language field names throughout. Agents use this domain
|
|
5
|
+
for HITL routing, escalation logic, and approval-rights reasoning.
|
|
6
|
+
|
|
7
|
+
Field names are developer-facing; when narrating to users, say "role", "responsibilities",
|
|
8
|
+
"reports to", and "held by". Do not say "seat", "accountability", or "EOS".
|
|
9
|
+
|
|
10
|
+
## Schema
|
|
11
|
+
|
|
12
|
+
Source: `packages/core/src/organization-model/domains/roles.ts`
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
RolesDomainSchema = z.object({
|
|
16
|
+
roles: z.array(RoleSchema).default([])
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
RoleSchema = z.object({
|
|
20
|
+
id: z.string().trim().min(1).max(100), // stable ID, e.g. "role-ceo"
|
|
21
|
+
title: z.string().trim().min(1).max(200), // display title, e.g. "CEO"
|
|
22
|
+
responsibilities: z.array(z.string().trim().max(500)).default([]),// what this role owns
|
|
23
|
+
reportsToId: z.string().trim().min(1).max(100).optional(), // must ref another roles[].id
|
|
24
|
+
heldBy: z.string().trim().max(200).optional() // name or email, free-form
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Field reference
|
|
29
|
+
|
|
30
|
+
| Field | Type | Max | Notes |
|
|
31
|
+
| ------------------ | -------- | --- | --------------------------------------------------------------- |
|
|
32
|
+
| `id` | string | 100 | Stable key, min 1 char; e.g. `"role-ceo"` |
|
|
33
|
+
| `title` | string | 200 | Display title; min 1 char required |
|
|
34
|
+
| `responsibilities` | string[] | 500 | Each item: one thing this role is accountable for |
|
|
35
|
+
| `reportsToId` | string | 100 | Optional; must reference another `roles[].id` in the collection |
|
|
36
|
+
| `heldBy` | string | 200 | Optional; name or email of the person holding this role |
|
|
37
|
+
|
|
38
|
+
## Validation rules
|
|
39
|
+
|
|
40
|
+
- `reportsToId` (when present) must resolve to another `roles[].id` in the same collection;
|
|
41
|
+
enforced at parse time by `OrganizationModelSchema.superRefine()`
|
|
42
|
+
- Absence of `reportsToId` indicates a top-level role (no reporting line)
|
|
43
|
+
- Cycle detection is not enforced by the schema (known limitation); agents should surface
|
|
44
|
+
obvious cycles (e.g. role A reports to role B which reports to role A)
|
|
45
|
+
- `heldBy` is free-form; no validation beyond max length
|
|
46
|
+
- An empty roles array means no HITL routing or escalation rules are available
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
roles: {
|
|
52
|
+
roles: [
|
|
53
|
+
{
|
|
54
|
+
id: "role-ceo",
|
|
55
|
+
title: "CEO",
|
|
56
|
+
responsibilities: [
|
|
57
|
+
"Set company direction",
|
|
58
|
+
"Final approval on deals >$10K",
|
|
59
|
+
"Manage investor relations"
|
|
60
|
+
],
|
|
61
|
+
reportsToId: undefined,
|
|
62
|
+
heldBy: "Alice Johnson"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "role-head-of-client-success",
|
|
66
|
+
title: "Head of Client Success",
|
|
67
|
+
responsibilities: [
|
|
68
|
+
"Own client health scores",
|
|
69
|
+
"Lead quarterly business reviews",
|
|
70
|
+
"Handle escalations"
|
|
71
|
+
],
|
|
72
|
+
reportsToId: "role-ceo",
|
|
73
|
+
heldBy: undefined
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Where it lives in the adapter
|
|
80
|
+
|
|
81
|
+
`foundations/config/organization-model.ts` under the `roles` key of
|
|
82
|
+
`defineOrganizationModel({...})`.
|
|
83
|
+
|
|
84
|
+
To read the current role chart: open the adapter file and inspect the `roles.roles` array, or
|
|
85
|
+
use `pnpm exec elevasis-sdk knowledge:cat roles` (external project).
|
|
86
|
+
|
|
87
|
+
## Write path
|
|
88
|
+
|
|
89
|
+
To add, edit, or remove a role, the `/knowledge` skill runs the codify ceremony
|
|
90
|
+
(`operations/codify-level-a.md`): snapshot → propose → confirm → write → typecheck → Zod parse →
|
|
91
|
+
rollback on failure. Only the `roles` array is written; no other keys in the adapter are touched.
|
|
92
|
+
Before writing, the skill verifies all `reportsToId` references resolve to IDs that will exist
|
|
93
|
+
after the write. When removing a role, the skill surfaces any other roles that `reportsToId` to it
|
|
94
|
+
and asks whether to clear those reporting lines before proceeding.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
**Read via `/knowledge`** — natural-language queries like "who is responsible for client
|
|
99
|
+
escalations?" or "list my roles" route to this domain via the skill's intent classifier.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# TechStack domain
|
|
2
|
+
|
|
3
|
+
Tech stack information is not a standalone top-level domain — it lives as an optional `techStack`
|
|
4
|
+
extension field on individual `ResourceMapping` entries in the organization model. This keeps all
|
|
5
|
+
integration metadata co-located with the resource mapping that represents it, while adding fields
|
|
6
|
+
that agents need for cross-integration automation and system-of-record resolution.
|
|
7
|
+
|
|
8
|
+
## Schema
|
|
9
|
+
|
|
10
|
+
Source: `packages/core/src/organization-model/domains/shared.ts`
|
|
11
|
+
|
|
12
|
+
```typescript
|
|
13
|
+
TechStackEntrySchema = z.object({
|
|
14
|
+
platform: z.string().trim().min(1).max(200),
|
|
15
|
+
purpose: z.string().trim().min(1).max(500),
|
|
16
|
+
credentialStatus: z.enum(['configured', 'pending', 'expired', 'missing']),
|
|
17
|
+
isSystemOfRecord: z.boolean().default(false)
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`TechStackEntrySchema` is an optional field on `ResourceMappingSchema`. It applies to resource
|
|
22
|
+
mapping entries whose `resourceType` is `'integration'` or `'external'`.
|
|
23
|
+
|
|
24
|
+
## Field reference
|
|
25
|
+
|
|
26
|
+
| Field | Type | Notes |
|
|
27
|
+
| ------------------ | ------- | ---------------------------------------------------------------------- |
|
|
28
|
+
| `platform` | string | Name of the external platform; e.g. `"HubSpot"`, `"Stripe"`, `"Apify"` |
|
|
29
|
+
| `purpose` | string | Free-form description of what this integration is used for |
|
|
30
|
+
| `credentialStatus` | enum | `configured`, `pending`, `expired`, or `missing` |
|
|
31
|
+
| `isSystemOfRecord` | boolean | `true` if this integration is the authoritative source for its domain |
|
|
32
|
+
|
|
33
|
+
## Validation rules
|
|
34
|
+
|
|
35
|
+
- `platform` and `purpose` are required (min 1 char)
|
|
36
|
+
- `credentialStatus` must be one of the four enum values; no free-form strings
|
|
37
|
+
- `isSystemOfRecord` defaults to `false`; only one integration per domain should be `true`,
|
|
38
|
+
though the schema does not enforce uniqueness — agents should surface conflicts
|
|
39
|
+
- `techStack` applies only to resource mappings with `resourceType: 'integration'` or
|
|
40
|
+
`'external'`; adding it to other resource types is valid at schema level but semantically
|
|
41
|
+
incorrect
|
|
42
|
+
|
|
43
|
+
`credentialStatus` semantics:
|
|
44
|
+
|
|
45
|
+
- `configured` -- credential present and active
|
|
46
|
+
- `pending` -- integration planned but not yet set up
|
|
47
|
+
- `expired` -- credential previously configured but has lapsed
|
|
48
|
+
- `missing` -- expected to be configured but not present
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// Inside resourceMappings array in defineOrganizationModel({...})
|
|
54
|
+
resourceMappings: [
|
|
55
|
+
{
|
|
56
|
+
id: "rm-hubspot",
|
|
57
|
+
label: "HubSpot CRM Integration",
|
|
58
|
+
resourceType: "integration",
|
|
59
|
+
techStack: {
|
|
60
|
+
platform: "HubSpot",
|
|
61
|
+
purpose: "CRM for contacts, companies, and deal pipeline",
|
|
62
|
+
credentialStatus: "configured",
|
|
63
|
+
isSystemOfRecord: true
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: "rm-apify",
|
|
68
|
+
label: "Apify Web Scraping",
|
|
69
|
+
resourceType: "integration",
|
|
70
|
+
techStack: {
|
|
71
|
+
platform: "Apify",
|
|
72
|
+
purpose: "Web scraping and data extraction for lead enrichment",
|
|
73
|
+
credentialStatus: "pending",
|
|
74
|
+
isSystemOfRecord: false
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Where it lives in the adapter
|
|
81
|
+
|
|
82
|
+
`foundations/config/organization-model.ts` inside the `resourceMappings` array of
|
|
83
|
+
`defineOrganizationModel({...})`. The `techStack` field is set on the matching `ResourceMapping`
|
|
84
|
+
object by `id`.
|
|
85
|
+
|
|
86
|
+
To read current tech stack entries: open the adapter file and inspect the `resourceMappings`
|
|
87
|
+
array, filtering to entries with a `techStack` field, or use
|
|
88
|
+
`pnpm exec elevasis-sdk knowledge:cat techStack` (external project).
|
|
89
|
+
|
|
90
|
+
## Write path
|
|
91
|
+
|
|
92
|
+
To add or update `techStack` metadata on a resource mapping, the `/knowledge` skill runs the
|
|
93
|
+
codify ceremony (`operations/codify-level-a.md`): snapshot → propose → confirm → write →
|
|
94
|
+
typecheck → Zod parse → rollback on failure. Only the targeted `resourceMappings` entry (matched
|
|
95
|
+
by `id`) is modified; all other entries are left unchanged. If the user only wants to update
|
|
96
|
+
`credentialStatus`, a targeted edit to that single field is preferred.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
**Read via `/knowledge`** — natural-language queries like "what integrations are configured?" or
|
|
101
|
+
"is HubSpot our system of record for contacts?" route to this domain via the skill's intent
|
|
102
|
+
classifier.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-ui
|
|
3
|
+
description: Start the project's Vite UI dev server on port 4300 in the background, surfacing the URL once it's ready. Detects port conflicts and asks before killing the holder.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run UI
|
|
7
|
+
|
|
8
|
+
Start `ui/` dev server (`pnpm -C ui dev`) in the background on port 4300 and surface the URL when Vite reports ready.
|
|
9
|
+
|
|
10
|
+
**Usage:** `/run-ui`
|
|
11
|
+
|
|
12
|
+
The Vite config in `ui/vite.config.ts` pins port 4300 with `strictPort: true`, so a conflict is a hard fail — the skill resolves the conflict before launching.
|
|
13
|
+
|
|
14
|
+
## Process
|
|
15
|
+
|
|
16
|
+
### Step 1: Probe port 4300
|
|
17
|
+
|
|
18
|
+
Run via PowerShell tool (Windows-native, cleanest):
|
|
19
|
+
|
|
20
|
+
```powershell
|
|
21
|
+
$conn = Get-NetTCPConnection -LocalPort 4300 -State Listen -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
22
|
+
if ($conn) {
|
|
23
|
+
$proc = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
|
|
24
|
+
$cmd = (Get-CimInstance Win32_Process -Filter "ProcessId = $($conn.OwningProcess)" -ErrorAction SilentlyContinue).CommandLine
|
|
25
|
+
"PID=$($conn.OwningProcess) NAME=$($proc.ProcessName) CMD=$cmd"
|
|
26
|
+
} else {
|
|
27
|
+
"FREE"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Step 2: Branch on probe result
|
|
32
|
+
|
|
33
|
+
- **`FREE`** → go to Step 3.
|
|
34
|
+
- **Holder is our Vite** (CMD contains `vite` or `node` running from this project's `ui/`) → port is already serving the app. Skip launch and surface `http://localhost:4300/` directly. Done.
|
|
35
|
+
- **Holder is something else** → ask the user:
|
|
36
|
+
|
|
37
|
+
> "Port 4300 is held by `<NAME>` (PID `<PID>`). Kill it and start the dev server? (y/n)"
|
|
38
|
+
|
|
39
|
+
On `n`, abort with no further action. On `y`, run `Stop-Process -Id <PID> -Force` then continue to Step 3.
|
|
40
|
+
|
|
41
|
+
### Step 3: Launch dev server in background
|
|
42
|
+
|
|
43
|
+
Use Bash tool with `run_in_background: true`:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pnpm -C ui dev
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Capture the returned shell ID.
|
|
50
|
+
|
|
51
|
+
### Step 4: Wait for ready signal
|
|
52
|
+
|
|
53
|
+
Poll the background shell output (read every ~2s) for Vite's ready line — typically:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
➜ Local: http://localhost:4300/
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
or `ready in <N>ms`.
|
|
60
|
+
|
|
61
|
+
Stop polling on the first match. Hard cap: ~15 seconds (≈7 reads). If no ready signal arrives, surface the last 20 lines of background output so the user can debug, and leave the background process running.
|
|
62
|
+
|
|
63
|
+
### Step 5: Report
|
|
64
|
+
|
|
65
|
+
On success:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
UI dev server running
|
|
69
|
+
Local: http://localhost:4300/
|
|
70
|
+
Shell: <bg-shell-id>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
On timeout, prepend a one-line note ("Vite did not report ready within 15s — last output:") before the captured tail.
|