@elevasis/sdk 1.33.1 → 1.34.1

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.
@@ -55,6 +55,10 @@ metadata:
55
55
  - show me all reference docs
56
56
  - where does
57
57
  - apply
58
+ - build a system
59
+ - design a system
60
+ - create a system that
61
+ - system architecture
58
62
  allowed-tools: Read, Write, Edit, Glob, Grep, Bash
59
63
  ---
60
64
 
@@ -87,18 +91,34 @@ Auto-invocation is driven by frontmatter `description`, `metadata.pathPatterns`,
87
91
 
88
92
  ---
89
93
 
90
- ## 5-Bucket Decision Tree
94
+ ## Operations
95
+
96
+ | Operation | Description | Execute |
97
+ | --------- | ------------------------------------------------------------------------------------------------------------------------ | --------------------------------------- |
98
+ | `build` | Codify-ceremony runbook for building a System end to end (shell → ontology → resources → topology → knowledge → verify). | `.claude/skills/om/operations/build.md` |
99
+
100
+ ---
91
101
 
92
- Once invoked, classify the user's input into ONE of these buckets and dispatch the matching
93
- primitive. When two buckets fit, prefer the higher one (more specific → more general).
102
+ ## 5-Bucket Decision Tree
94
103
 
95
- | # | Bucket | Trigger | Dispatch |
96
- | --- | ------------------------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
97
- | 1 | Named knowledge/role/policy id | User names `knowledge.<id>`, `role.<id>`, `policy.<id>` directly | `om:cat <id>` for body, `om:describe <id>` for neighborhood |
98
- | 2 | Named system | User names a system path (`sales.crm`, `sales.lead-gen`) | `om:describe <id>` |
99
- | 3 | Named ontology id | Id contains `:object/`, `:action/`, `:event/`, `:catalog/`, `:interface/`, `:link/`, `:surface/` | `om:describe <id>` (or `om:ls /by-ontology/<id> --ids-only` then `om:cat` each) |
100
- | 4 | Kind keyword | "playbooks", "strategies", "all references", "list policies" | `om:ls /by-kind/<kind> --ids-only` then `om:cat` each |
101
- | 5 | Free-text discovery | Anything else ("lead gen", "outreach", "what governs X?") | `om:search "<query>"` then drill into top hit with `om:describe` |
104
+ If the user expresses intent to **build, design, or architect a system** -- phrased as "build a
105
+ system", "design a system", "create a system that does X", "I want a system for Y", "system
106
+ architecture for Z", or any free-text describing a system they want to construct rather than
107
+ query -- route to `/om build` **before** the buckets below. Read
108
+ `.claude/skills/om/operations/build.md` and follow its ordered phases. This is the primary
109
+ entry; the user does not need to type `/om build` explicitly.
110
+
111
+ Once invoked for read/write intents (not build), classify the user's input into ONE of these
112
+ buckets and dispatch the matching primitive. When two buckets fit, prefer the higher one (more
113
+ specific → more general).
114
+
115
+ | # | Bucket | Trigger | Dispatch |
116
+ | --- | ------------------------------ | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
117
+ | 1 | Named knowledge/role/policy id | User names `knowledge.<id>`, `role.<id>`, `policy.<id>` directly | `om:cat <id>` for body, `om:describe <id>` for neighborhood |
118
+ | 2 | Named system | User names a system path (`sales.crm`, `sales.lead-gen`) | `om:describe <id>` |
119
+ | 3 | Named ontology id | Id contains `:object/`, `:action/`, `:event/`, `:catalog/`, `:interface/`, `:link/`, `:endpoint/` | `om:describe <id>` (or `om:ls /by-ontology/<id> --ids-only` then `om:cat` each) |
120
+ | 4 | Kind keyword | "playbooks", "strategies", "all references", "list policies" | `om:ls /by-kind/<kind> --ids-only` then `om:cat` each |
121
+ | 5 | Free-text discovery | Anything else ("lead gen", "outreach", "what governs X?") | `om:search "<query>"` then drill into top hit with `om:describe` |
102
122
 
103
123
  On ambiguous input, default to **bucket 5 (search)** and surface the top hits. Codify and Toggle
104
124
  intents are write paths -- see "Write Power" below.
@@ -107,17 +127,20 @@ intents are write paths -- see "Write Power" below.
107
127
 
108
128
  ## CLI Surface
109
129
 
110
- All commands run with `pnpm exec elevasis-sdk <cmd>` (or the `om:` alias of the legacy `knowledge:` name).
111
-
112
- | Command | Alias | Purpose |
113
- | ------------------ | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
114
- | `om:search <q>` | `knowledge:search` | Universal keyword search across all 6 OM surfaces |
115
- | `om:describe <id>` | `knowledge:describe` | Structured neighborhood view; kind auto-detected from id shape |
116
- | `om:cat <id>` | `knowledge:cat` | Raw MDX body of a knowledge node |
117
- | `om:ls <path>` | `knowledge:ls` | List by mount path. Enumeration: `/all-systems`, `/all-resources`, `/all-roles`. Scoped: `/by-system/`, `/by-kind/`, `/by-ontology/`, `/by-owner/`, `/graph/<id>/{governs,governed-by}` |
118
- | `om:graph <id>` | `knowledge:graph` | Show outgoing + incoming graph edges |
119
- | `om:skills <id>` | `knowledge:skills` | Show callable invocations on graph neighbors |
120
- | `om:generate` | `knowledge:generate` | Regenerate `_generated/nodes.ts` from MDX sources |
130
+ All commands run with `pnpm elevasis-sdk <cmd>` from the tenant project root (uses the root script
131
+ alias). Alternatively, use `pnpm -C operations exec elevasis-sdk <cmd>` from the monorepo root.
132
+ Do NOT use `pnpm exec elevasis-sdk <cmd>` at the project root -- `@elevasis/sdk` is a dependency of
133
+ `operations/` only; the binary is not found from the project root without the alias.
134
+
135
+ | Command | Alias | Purpose |
136
+ | ------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
137
+ | `om:search <q>` | `knowledge:search` | Universal keyword search across all 6 OM surfaces |
138
+ | `om:describe <id>` | `knowledge:describe` | Structured neighborhood view; kind auto-detected from id shape; also resolves `item:<domain>:<id>` and bare `<prefix>:<uuid>` domain-item forms |
139
+ | `om:cat <id>` | `knowledge:cat` | Raw MDX body of a knowledge node |
140
+ | `om:ls <path>` | `knowledge:ls` | List by mount path. Enumeration: `/all-systems`, `/all-resources`, `/all-roles`. Scoped: `/by-system/`, `/by-kind/`, `/by-ontology/`, `/by-owner/`, `/by-domain/`, `/by-item/`, `/graph/<id>/{governs,governed-by}` |
141
+ | `om:graph <id>` | `knowledge:graph` | Show outgoing + incoming graph edges |
142
+ | `om:skills <id>` | `knowledge:skills` | Show callable invocations on graph neighbors |
143
+ | `om:generate` | `knowledge:generate` | Regenerate `_generated/nodes.ts` from MDX sources |
121
144
 
122
145
  Common flags: `--json`, `--ids-only`, `--limit <n>`, `--kinds <list>`.
123
146
 
@@ -128,23 +151,42 @@ Common flags: `--json`, `--ids-only`, `--limit <n>`, `--kinds <list>`.
128
151
  ### Free-text discovery (default for natural-language queries)
129
152
 
130
153
  ```bash
131
- pnpm exec elevasis-sdk om:search "lead gen"
132
- pnpm exec elevasis-sdk om:search outreach --kinds knowledge --limit 5
133
- pnpm exec elevasis-sdk om:search apollo --ids-only
154
+ pnpm elevasis-sdk om:search "lead gen"
155
+ pnpm elevasis-sdk om:search outreach --kinds knowledge --limit 5
156
+ pnpm elevasis-sdk om:search apollo --ids-only
134
157
  ```
135
158
 
136
159
  ### Neighborhood view for any OM node
137
160
 
138
161
  ```bash
139
- pnpm exec elevasis-sdk om:describe sales.crm
140
- pnpm exec elevasis-sdk om:describe knowledge.outreach-playbook
141
- pnpm exec elevasis-sdk om:describe sales.crm:object/deal
162
+ pnpm elevasis-sdk om:describe sales.crm
163
+ pnpm elevasis-sdk om:describe knowledge.outreach-playbook
164
+ pnpm elevasis-sdk om:describe sales.crm:object/deal
142
165
  ```
143
166
 
167
+ ### Domain-item profile (clients, roles, policies, customers, offerings, goals)
168
+
169
+ Use `om:describe item:<domain>:<id>` to read a rich domain-item profile -- identity, branding,
170
+ location, and governing knowledge. The bare `<prefix>:<uuid>` form (e.g. `client:<uuid>`) is
171
+ accepted as a back-compat alias and resolves identically.
172
+
173
+ ```bash
174
+ pnpm elevasis-sdk om:describe item:clients:<uuid> # full ClientProfile + location + governing knowledge
175
+ pnpm elevasis-sdk om:describe item:roles:<id>
176
+ pnpm elevasis-sdk om:describe item:policies:<id>
177
+ pnpm elevasis-sdk om:describe item:customers:<id>
178
+ pnpm elevasis-sdk om:describe item:offerings:<id>
179
+ pnpm elevasis-sdk om:describe item:goals:<id>
180
+ ```
181
+
182
+ Do not confuse this with `client:get <uuid>` (the portfolio/DB surface for status, lineage, and
183
+ deals). `om:describe item:clients:<uuid>` returns the org-model `ClientProfile`; `client:get`
184
+ returns a sparse DB record. They share the same `id` and can be cross-linked by it.
185
+
144
186
  ### Read a single knowledge node body
145
187
 
146
188
  ```bash
147
- pnpm exec elevasis-sdk om:cat knowledge.outreach-playbook
189
+ pnpm elevasis-sdk om:cat knowledge.outreach-playbook
148
190
  ```
149
191
 
150
192
  ### Top-level enumeration (drill-down entry point)
@@ -153,10 +195,10 @@ Start here when an agent needs to discover what this tenant's custom OM contains
153
195
  building on it -- list everything in a domain, then narrow with `om:describe` / `om:cat`:
154
196
 
155
197
  ```bash
156
- pnpm exec elevasis-sdk om:ls /all-systems # every System (path + label)
157
- pnpm exec elevasis-sdk om:ls /all-resources # every resource (id, kind, title)
158
- pnpm exec elevasis-sdk om:ls /all-roles # every role (id, title)
159
- pnpm exec elevasis-sdk om:ls /all-systems --ids-only # pipe paths into om:describe
198
+ pnpm elevasis-sdk om:ls /all-systems # every System (path + label)
199
+ pnpm elevasis-sdk om:ls /all-resources # every resource (id, kind, title)
200
+ pnpm elevasis-sdk om:ls /all-roles # every role (id, title)
201
+ pnpm elevasis-sdk om:ls /all-systems --ids-only # pipe paths into om:describe
160
202
  ```
161
203
 
162
204
  These resolve against this tenant's resolved model -- they enumerate the project's own custom
@@ -165,11 +207,13 @@ OM, not the platform's. Use `--json` for the wrapped envelope or `--ids-only` fo
165
207
  ### Scoped mount-path listings
166
208
 
167
209
  ```bash
168
- pnpm exec elevasis-sdk om:ls /by-system/sales.crm
169
- pnpm exec elevasis-sdk om:ls /by-kind/playbook --ids-only
170
- pnpm exec elevasis-sdk om:ls /by-ontology/sales.crm:object/deal --ids-only
171
- pnpm exec elevasis-sdk om:ls /by-owner/role.ops-lead --ids-only
172
- pnpm exec elevasis-sdk om:graph knowledge.outreach-playbook
210
+ pnpm elevasis-sdk om:ls /by-system/sales.crm
211
+ pnpm elevasis-sdk om:ls /by-kind/playbook --ids-only
212
+ pnpm elevasis-sdk om:ls /by-ontology/sales.crm:object/deal --ids-only
213
+ pnpm elevasis-sdk om:ls /by-owner/role.ops-lead --ids-only
214
+ pnpm elevasis-sdk om:ls /by-domain/clients # enumerate all client domain items
215
+ pnpm elevasis-sdk om:ls /by-item/clients/<uuid> # single item record (same as om:describe item:clients:<uuid>)
216
+ pnpm elevasis-sdk om:graph knowledge.outreach-playbook
173
217
  ```
174
218
 
175
219
  When a query clearly names an ontology id such as `sales.crm:object/deal`, route through
@@ -179,17 +223,31 @@ When a query clearly names an ontology id such as `sales.crm:object/deal`, route
179
223
 
180
224
  ### `/om read-folder` (chat shorthand from the Knowledge Browser)
181
225
 
182
- The Knowledge Browser's copy button on a top-level system or kind group emits a single
183
- `/om read-folder <axis>:<id>` line (or the legacy `/knowledge read-folder ...` form) instead of
184
- N per-node `read` lines. Resolve it by listing the folder via `om:ls` and reading each child:
226
+ The Knowledge Browser's copy button on a top-level system, kind group, or domain-item node
227
+ emits a single `/om read-folder <axis>:<id>` line (or the legacy `/knowledge read-folder ...`
228
+ form) instead of N per-node `read` lines. Resolve it by the table below:
229
+
230
+ | Copy form | Resolution |
231
+ | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
232
+ | `/om read-folder system:<id>` | `pnpm elevasis-sdk om:ls /by-system/<id> --ids-only`, then `om:cat` each |
233
+ | `/om read-folder kind:<kind>` | `pnpm elevasis-sdk om:ls /by-kind/<kind> --ids-only`, then `om:cat` each |
234
+ | `/om read-folder owner:<id>` | `pnpm elevasis-sdk om:ls /by-owner/<id> --ids-only`, then `om:cat` each |
235
+ | `/om read-folder ontology:<id>` | `pnpm elevasis-sdk om:ls /by-ontology/<id> --ids-only`, then `om:cat` each |
236
+ | `/om read-folder item:<domain>:<id>` | `pnpm elevasis-sdk om:describe item:<domain>:<id>` -- returns profile + location + governing knowledge |
237
+ | `/om read-folder graph:<id>` | inspect `/graph/<id>/governs` and `/graph/<id>/governed-by`; read returned knowledge ids |
238
+ | `/om read-folder group:<id>` | browser overview reference only; resolve by visible children -- `pnpm elevasis-sdk om:ls /by-system/<id> --ids-only` |
239
+ | `/om read-folder domain:<domain>` | browser overview reference only; resolve by enumerating domain -- `pnpm elevasis-sdk om:ls /by-domain/<domain> --ids-only` |
240
+ | `/om read-folder folder:<id>` | browser overview reference only; treat as `domain:<id>` and enumerate with `/by-domain/<id>` |
241
+
242
+ **Legacy bridge -- `graph:client:<uuid>` and other `graph:<prefix>:<uuid>` domain-item forms:**
243
+ Older Knowledge Browser builds emitted `graph:client:<uuid>` for client items. This is a
244
+ graph-neighborhood shorthand, not a profile read. When you receive such a reference:
245
+
246
+ 1. Resolve the graph neighborhood: `pnpm elevasis-sdk om:graph client:<uuid>` (may return empty or only `contains` edges -- that is expected; no `ClientProfile` is accessible this way).
247
+ 2. For the rich profile, pivot to: `pnpm elevasis-sdk om:describe item:clients:<uuid>`.
185
248
 
186
- | Copy form | Resolution |
187
- | ------------------------------- | ---------------------------------------------------------------------------------------- |
188
- | `/om read-folder system:<id>` | `pnpm exec elevasis-sdk om:ls /by-system/<id> --ids-only`, then `om:cat` each |
189
- | `/om read-folder kind:<kind>` | `pnpm exec elevasis-sdk om:ls /by-kind/<kind> --ids-only`, then `om:cat` each |
190
- | `/om read-folder owner:<id>` | `pnpm exec elevasis-sdk om:ls /by-owner/<id> --ids-only`, then `om:cat` each |
191
- | `/om read-folder ontology:<id>` | `pnpm exec elevasis-sdk om:ls /by-ontology/<id> --ids-only`, then `om:cat` each |
192
- | `/om read-folder graph:<id>` | inspect `/graph/<id>/governs` and `/graph/<id>/governed-by`; read returned knowledge ids |
249
+ In short: `graph:client:<uuid>` points to the graph node; `item:clients:<uuid>` resolves the
250
+ full org-model profile. Always use `item:` for profile reads going forward.
193
251
 
194
252
  Dotted system ids may use either dots or slashes (`sales.crm` and `sales/crm` both work).
195
253
  Legacy `feature:<id>` copy lines from older browser builds are compatibility aliases for
@@ -261,8 +319,8 @@ Placement examples:
261
319
 
262
320
  Before adding a System:
263
321
 
264
- 1. Run `pnpm exec elevasis-sdk om:ls /all-systems`.
265
- 2. Run `pnpm exec elevasis-sdk om:describe <candidate-parent-or-owner>`.
322
+ 1. Run `pnpm elevasis-sdk om:ls /all-systems`.
323
+ 2. Run `pnpm elevasis-sdk om:describe <candidate-parent-or-owner>`.
266
324
  3. If the proposed System name is a resource kind, shell group, or catch-all, do not create it;
267
325
  attach or create a Resource under the real owning System.
268
326
  4. Create a new System only when no existing System owns the capability and the new System has
@@ -414,4 +472,4 @@ classification names a specific domain.
414
472
 
415
473
  ---
416
474
 
417
- **Last Updated:** 2026-05-14
475
+ **Last Updated:** 2026-06-06
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: build
3
+ description: Guided Codify-ceremony runbook for building a new Organization Model System end to end in a tenant project — shell, ontology, resources, topology, knowledge node, and verify.
4
+ allowed-tools: Read, Glob, Grep, Bash
5
+ ---
6
+
7
+ # /om build (Tenant)
8
+
9
+ Intent-driven runbook for authoring a complete Organization Model System in this tenant project.
10
+ The **primary entry is intent**: `/om` routes free-text build intent here via `promptSignals` and
11
+ the 5-bucket classifier whenever you describe a system you want to build. Manual `/om build` is a
12
+ supported secondary entry.
13
+
14
+ Every write runs through the Codify ceremony (snapshot → propose → confirm → write → validate →
15
+ rollback). See the "Write Power" section in `SKILL.md` for the ceremony steps.
16
+
17
+ **Tenant authoring files** (split layout):
18
+
19
+ - `core/config/organization-model/systems.ts` — System entries and system-owned resources
20
+ - `core/config/organization-model/navigation.ts` — sidebar wiring
21
+ - `core/config/knowledge/nodes/` — knowledge node MDX files
22
+
23
+ ---
24
+
25
+ ## Phase 0 — Capture Intent
26
+
27
+ Before writing anything, extract:
28
+
29
+ 1. **System name and dotted path** (`parent.child` format, e.g. `sales.crm`).
30
+ 2. **Kind**: `product`, `operational`, `platform`, or `diagnostic`.
31
+ 3. **What it does** — one sentence. This becomes the `description`.
32
+ 4. **What it owns** — objects, actions, catalogs, events (these become `system.ontology` entries).
33
+ 5. **What it calls or reacts to** — other systems, triggers, human checkpoints.
34
+ 6. **Whether it needs a UI route** — yes/no determines whether `system.ui` is authored.
35
+ 7. **Whether it adopts a platform API interface** — yes/no determines whether `system.apiInterface`
36
+ is authored (see "API Interface Readiness" in `SKILL.md`).
37
+
38
+ Run a pre-flight read to ground id choices in current model state:
39
+
40
+ ```bash
41
+ pnpm elevasis-sdk om:ls /all-systems
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Phase 1 — System Shell (Codify Level-A)
47
+
48
+ Use `om:scaffold:system` (dry-run first) or the Codify Level-A ceremony to add the `SystemEntry`
49
+ to `core/config/organization-model/systems.ts`.
50
+
51
+ **Dry-run:**
52
+
53
+ ```bash
54
+ pnpm elevasis-sdk om:scaffold:system --dry-run
55
+ ```
56
+
57
+ Minimum fields: `id`, `order`, `label`. Optional at this stage: `description`, `kind`,
58
+ `lifecycle`, `responsibleRoleId`.
59
+
60
+ **Validate after write:**
61
+
62
+ ```bash
63
+ pnpm -C operations check-types
64
+ pnpm -C operations check
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Phase 2 — Ontology (`system.ontology`)
70
+
71
+ Add owned ontology kinds inside the `ontology` field of the `SystemEntry` in `systems.ts`.
72
+
73
+ Valid scope keys: `objectTypes`, `linkTypes`, `actionTypes`, `catalogTypes`, `eventTypes`,
74
+ `interfaceTypes`, `valueTypes`, `sharedProperties`, `groups`, `endpoints`.
75
+
76
+ All ids use the canonical format: `system.path:kind/local-id`
77
+ (e.g. `sales.crm:object/deal`, `sales.crm:action/qualify-lead`).
78
+
79
+ Apply via the Codify Level-A ceremony — read, propose diff, confirm, write, validate.
80
+
81
+ **Validate after write:**
82
+
83
+ ```bash
84
+ pnpm -C operations check-types
85
+ pnpm -C operations check
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Phase 3 — Resources (Codify Level-A + scaffold)
91
+
92
+ Add resource entries to `systems.ts` (or the split `resources` section if your project uses one).
93
+ Each resource carries `systemPath` (canonical system attachment) and `ontology` bindings.
94
+
95
+ Use `om:scaffold:resource` for guided creation, or Codify Level-A for manual addition.
96
+
97
+ **Dry-run:**
98
+
99
+ ```bash
100
+ pnpm elevasis-sdk om:scaffold:resource --dry-run --system-path <your.system>
101
+ ```
102
+
103
+ Key invariants:
104
+
105
+ - `resource.systemPath` is the canonical attachment for `getResourcesForSystem()`.
106
+ - Choose `systemPath` based on the business capability the resource operates, not its kind.
107
+ - `primaryAction` must be a member of `resource.ontology.actions`.
108
+
109
+ **Validate after write:**
110
+
111
+ ```bash
112
+ pnpm -C operations check-types
113
+ pnpm -C operations check
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Phase 4 — Topology (optional)
119
+
120
+ If the system reacts to events, calls other systems, or requires human checkpoints, author
121
+ topology relationships. In a tenant project, topology lives alongside the System entries in
122
+ `systems.ts` (or a dedicated `topology` field if your project uses the split layout with a
123
+ separate topology section).
124
+
125
+ Canonical relationship kinds:
126
+
127
+ - `triggers` — event, webhook, or schedule fires a resource handler
128
+ - `uses` — this system calls another system or integration
129
+ - `approval` — a step requires human checkpoint before continuing
130
+
131
+ Cross-system API handoff requires a `uses` edge with `systemInterfaceGrant` metadata — see the
132
+ "API Interface Readiness" section in `SKILL.md`.
133
+
134
+ Apply via Codify Level-A ceremony. Validate after each topology write.
135
+
136
+ ---
137
+
138
+ ## Phase 5 — Knowledge Node (optional)
139
+
140
+ Author a governing knowledge node to make the system searchable via `/om` and surfaced in the
141
+ knowledge browser.
142
+
143
+ Use `om:scaffold:knowledge` for guided creation:
144
+
145
+ ```bash
146
+ pnpm elevasis-sdk om:scaffold:knowledge --dry-run --system-path <your.system> --kind playbook
147
+ ```
148
+
149
+ MDX frontmatter shape:
150
+
151
+ ```mdx
152
+ ---
153
+ id: knowledge.my-system-playbook
154
+ kind: playbook
155
+ label: My System Playbook
156
+ description: Rules and patterns for operating My System.
157
+ governs:
158
+ - my.system
159
+ ---
160
+ ```
161
+
162
+ After authoring, regenerate the knowledge index:
163
+
164
+ ```bash
165
+ pnpm elevasis-sdk om:generate
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Phase 6 — UI and Navigation (optional)
171
+
172
+ If the system needs a sidebar entry, author `system.ui` and add a navigation surface entry.
173
+
174
+ `system.ui` fields: `path`, `surfaces[]`, `icon`, `order`. Apply via Codify Level-A.
175
+
176
+ Navigation wiring lives in `core/config/organization-model/navigation.ts`. Add the system's
177
+ path to the relevant sidebar section. Validate after the navigation write.
178
+
179
+ ---
180
+
181
+ ## Phase 7 — apiInterface (API-backed systems only)
182
+
183
+ `system.apiInterface` is adopt-only in tenant projects. Only add it when the system adopts a
184
+ platform-provided API capability from the installed `@elevasis/core` / `@elevasis/sdk` version.
185
+ Use only readiness profiles listed in
186
+ `node_modules/@elevasis/sdk/reference/scaffold/reference/system-interface-capabilities.md`.
187
+
188
+ The profile also fixes the required System path — do not invent a profile or repoint a cataloged
189
+ profile to a custom path.
190
+
191
+ Apply via Codify Level-A after confirming the readiness profile with the user:
192
+
193
+ ```bash
194
+ pnpm -C operations check-types
195
+ pnpm -C operations check # conformance gate fires here if the marker is incomplete
196
+ ```
197
+
198
+ ---
199
+
200
+ ## Phase 8 — Full Verify
201
+
202
+ Run both validation gates once all phases are done:
203
+
204
+ ```bash
205
+ pnpm -C operations check-types
206
+ pnpm -C operations check
207
+ ```
208
+
209
+ If the conformance gate reports a gaps file, apply it:
210
+
211
+ ```bash
212
+ pnpm elevasis-sdk om:scaffold:fill --gaps .elevasis/conformance-gaps.json --dry-run
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Quick Reference
218
+
219
+ | Phase | OM Slot | Authoring File | Ceremony |
220
+ | ----- | --------------------------------- | --------------------------------- | ----------------------- |
221
+ | 1 | `systems` map | `systems.ts` | Scaffold or Level-A |
222
+ | 2 | `system.ontology.<scope>` | `systems.ts` | Level-A |
223
+ | 3 | resources + `resource.systemPath` | `systems.ts` | Scaffold or Level-A |
224
+ | 4 | topology relationships | `systems.ts` / topology section | Level-A |
225
+ | 5 | `system.governedByKnowledge[]` | `knowledge/nodes/<path>/<id>.mdx` | Scaffold or Level-A |
226
+ | 6 | `system.ui` + navigation surfaces | `systems.ts` + `navigation.ts` | Level-A |
227
+ | 7 | `system.apiInterface` | `systems.ts` | Level-A (adopt-only) |
228
+ | 8 | — | — | `check` + `check-types` |
229
+
230
+ ---
231
+
232
+ ## Cross-Links
233
+
234
+ - Codify Level-A ceremony: `.claude/skills/om/operations/codify-level-a.md`
235
+ - Scaffold (guided new entries): `.claude/skills/om/operations/scaffold.md`
236
+ - API interface readiness: "API Interface Readiness" section in `.claude/skills/om/SKILL.md`
237
+ - Platform narrative guide + worked examples: `node_modules/@elevasis/sdk/reference/guides/building-systems.md` (if present)
@@ -115,9 +115,11 @@ Agents that need to pass structured JSON to `request:submit` or `exec` should wr
115
115
  pnpm elevasis-sdk exec my-workflow -f tmp/exec-payload.json --cleanup-input
116
116
  ```
117
117
 
118
- 3. The `--cleanup-input` flag deletes the file automatically after a successful command. On failure the file is left intact for inspection.
118
+ 3. The `--cleanup-input` flag deletes request/exec input files automatically after a successful command. On failure the file is left intact for inspection.
119
119
 
120
- **Safety guard:** `--cleanup-input` only deletes files that are under `<projectRoot>/tmp/`. If the resolved path is outside `tmp/`, the CLI prints a warning to stderr and leaves the file untouched. Files passed via `--input <json>` (inline JSON, no file) are never affected.
120
+ **Safety guard:** `--cleanup-input` only deletes files that are under `<projectRoot>/tmp/`. If the resolved path is outside `tmp/`, the CLI prints a warning to stderr and leaves the file untouched. Files passed via inline JSON flags are never affected.
121
+
122
+ Checklist commands in the currently published SDK use inline `--checklist` JSON only. In Windows PowerShell 5.1, inline JSON is not reliable; use bash/PowerShell 7 for those updates, or update the checklist through the UI.
121
123
 
122
124
  ---
123
125
 
@@ -298,11 +300,11 @@ Both `prj_milestones.checklist` and `prj_tasks.checklist` store a JSONB array of
298
300
  ]
299
301
  ```
300
302
 
301
- The CLI `--checklist` flag on both `project:milestone:update` and `project:task:update` performs a **full replace** the entire array is replaced with the JSON you supply. There are no item-level add/toggle/remove flags. To mutate a single item:
303
+ The CLI `--checklist` flag on `project:task:create`, `project:task:update`, and `project:milestone:update` performs a **full replace** where the command accepts checklist data. The entire array is replaced with the JSON you supply. There are no item-level add/toggle/remove flags. In Windows PowerShell 5.1, inline JSON is not reliable; use bash/PowerShell 7 for checklist CLI updates, or update the checklist through the UI. To mutate a single item:
302
304
 
303
305
  1. Read the current checklist (via psql or `project:task:get` / `project:milestone:list`)
304
306
  2. Mutate the array in memory (append, flip `completed`, filter out)
305
- 3. Write the entire array back via `--checklist '<json>'`
307
+ 3. Write the entire array back via `--checklist '<json-array>'`
306
308
 
307
309
  To clear a checklist: `--checklist '[]'`.
308
310
 
@@ -668,7 +670,7 @@ pnpm elevasis-sdk project:milestone:update <milestone-id> --status completed
668
670
 
669
671
  # Update checklist (full replace)
670
672
  pnpm elevasis-sdk project:milestone:update <milestone-id> \
671
- --checklist '[{"id":"uuid","label":"Item label","completed":false}]'
673
+ --checklist '[{"id":"1","label":"Review scope doc","completed":false}]'
672
674
  ```
673
675
 
674
676
  If status changes to `completed`, the API auto-sets `completed_at`.
@@ -679,7 +681,7 @@ If status changes to `completed`, the API auto-sets `completed_at`.
679
681
 
680
682
  1. Read the current checklist via psql or `project:milestone:list`
681
683
  2. Mutate the array in memory
682
- 3. Write back the full array via `--checklist '<json>'`
684
+ 3. Write back the full array via `--checklist '<json-array>'`
683
685
 
684
686
  ### `checklist <client> "<milestone>"` — View Checklist
685
687
 
@@ -741,7 +743,7 @@ pnpm elevasis-sdk project:task:create \
741
743
  pnpm elevasis-sdk project:task:create \
742
744
  --project <project-id> \
743
745
  --title "<name>" \
744
- --checklist '[{"id":"1","label":"Step one","completed":false}]'
746
+ --checklist '[{"id":"1","label":"Review scope doc","completed":false}]'
745
747
  ```
746
748
 
747
749
  ### `task update <client> "<task>" [options]` — Update Task
@@ -757,7 +759,7 @@ pnpm elevasis-sdk project:task:update <task-id> --status <status>
757
759
 
758
760
  # Update checklist (full replace)
759
761
  pnpm elevasis-sdk project:task:update <task-id> \
760
- --checklist '[{"id":"uuid","label":"Step","completed":false}]'
762
+ --checklist '[{"id":"1","label":"Review scope doc","completed":false}]'
761
763
 
762
764
  # Clear checklist
763
765
  pnpm elevasis-sdk project:task:update <task-id> --checklist '[]'
@@ -773,7 +775,7 @@ If status changes to `approved`, the API auto-sets `completed_at`.
773
775
 
774
776
  1. Read the current task via `project:task:get <task-id>`
775
777
  2. Mutate the checklist array in memory
776
- 3. Write back the full array via `project:task:update <task-id> --checklist '<json>'`
778
+ 3. Write back the full array via `project:task:update <task-id> --checklist '<json-array>'`
777
779
 
778
780
  ### `note <client> "<content>" [options]` — Add Note
779
781
 
@@ -964,15 +966,15 @@ When args don't match any command pattern, infer intent from natural language:
964
966
  | "what's overdue?" | List milestones where `due_date < now() AND status != 'completed'` |
965
967
  | "block acme, waiting on client credentials" | `update acme --status blocked` |
966
968
  | "show checklist for phase 2" | Read and display checklist for milestone "phase 2" via psql or `project:milestone:list` |
967
- | "add 'deploy staging' to task X's checklist" | Read task X's checklist → append `{id: uuid, label: "deploy staging", completed: false}` → `project:task:update <id> --checklist '<json>'` |
968
- | "mark 'deploy staging' done on task X" | Read task X's checklist → flip `completed` on matching item → `project:task:update <id> --checklist '<json>'` |
969
+ | "add 'deploy staging' to task X's checklist" | Read task X's checklist → append `{id: uuid, label: "deploy staging", completed: false}` → `project:task:update <id> --checklist '<json-array>'` |
970
+ | "mark 'deploy staging' done on task X" | Read task X's checklist → flip `completed` on matching item → `project:task:update <id> --checklist '<json-array>'` |
969
971
  | "clear the checklist on task X" | `project:task:update <task-id> --checklist '[]'` |
970
- | "add checklist item to onboarding milestone: review scope doc" | Read milestone checklist → append item → `project:milestone:update <id> --checklist '<json>'` |
972
+ | "add checklist item to onboarding milestone: review scope doc" | Read milestone checklist → append item → `project:milestone:update <id> --checklist '<json-array>'` |
971
973
  | "I'm done" / "task complete" / "done with this" | Resolve active task → confirm → `project:task:update <task-id> --status completed` |
972
974
  | "save: Apify actor X rate-limits at 20rps" | Resolve active project/task → `project:note:create --project <id> --type agent_learning --task <task-id> "Apify actor X rate-limits at 20rps"` |
973
975
  | "remember: client requires ISO dates, not timestamps" | Resolve active project/task → `project:note:create --project <id> --type agent_learning --task <task-id> "client requires ISO dates, not timestamps"` |
974
976
 
975
- **Checklist note:** all checklist mutations use the read-modify-write pattern. The CLI has no item-level flags (`--add-item`, `--toggle`, `--remove-item` do not exist). Always read the current state, mutate the array, then write the full array back.
977
+ **Checklist note:** all checklist mutations use the read-modify-write pattern. The CLI has no item-level flags (`--add-item`, `--toggle`, `--remove-item` do not exist). Always read the current state, mutate the array, then write the full array back. Use bash/PowerShell 7 for generated checklist JSON; Windows PowerShell 5.1 native argument passing is not reliable for inline JSON.
976
978
 
977
979
  ---
978
980
 
@@ -1078,7 +1080,7 @@ The full `client:*` surface (list, get, status, resolve) is available via `eleva
1078
1080
  6. **Template project assumption** — the template is a single-organization project. All
1079
1081
  `/project` operations operate within the organization scoped by `ELEVASIS_PLATFORM_KEY`.
1080
1082
  There is no cross-org capability.
1081
- 7. **Checklist full-replace** — the `--checklist` flag replaces the entire array. Always read
1083
+ 7. **Checklist full-replace** — `--checklist` replaces the entire array. Always read
1082
1084
  the current checklist before writing to avoid losing existing items.
1083
1085
  8. **Confirm task completion** — always ask once before marking a task `completed` via "I'm done"
1084
1086
  recognition. This status is semantically significant and warrants a confirmation step.
@@ -0,0 +1,29 @@
1
+ # Appearance Page Decoupled From App-Mode
2
+
3
+ ## Why this note exists
4
+
5
+ The Settings → Appearance page used to be hard-coupled to `dev-centric` app-mode: scaffold removed it under `--client-centric`, every `/external sync` actively deleted it (planner `delete` special-case), and verify forbade it for `client-centric` projects. That made the page silently vanish on every sync for client-centric tenants.
6
+
7
+ This train decouples Appearance from app-mode. Appearance is now an optional standalone page available in any mode. The only remaining app-mode difference is the `OrganizationSwitcher` in the topbar.
8
+
9
+ No npm publish is involved: the page renders the already-published `@elevasis/ui@2.46.0` `AppearanceSettings` component. The substrate changes (`scripts/external/*`) and the `_template` route are monorepo-internal and propagate through `/external sync`.
10
+
11
+ ## Applies to
12
+
13
+ - All template-derived projects under `external/` that lack `ui/src/routes/settings/appearance.tsx`.
14
+ - Confirmed pending at prep time: `nirvana-marketing` (sync planner `writes=1` for the appearance route). `contemplative-records` already restored it; `ZentaraHQ` shows no pending write.
15
+
16
+ ## Required actions
17
+
18
+ 1. The new template route `ui/src/routes/settings/appearance.tsx` propagates automatically via `/external sync` (registry entry `external-sync-feature-route-baseline`, `sync-preservation`). No manual file copy needed — running the prepared sync applies it.
19
+ 2. **Per-tenant nav entry is NOT propagated.** `core/config/organization-model/navigation.ts` is project-owned (sync-preservation). For any tenant that should surface Appearance in its sidebar, manually add a `settings-appearance` entry to `navigation.sidebar.bottom.settings.children` (order `50`, after `settings-webhooks`), pointing at the appearance route.
20
+
21
+ ## Verification
22
+
23
+ - After sync: `pnpm -C external/<project>/ui check-types` passes with the new route present.
24
+ - `pnpm sync:verify` reports `writes=0` for the synced project's `sync-plan`.
25
+ - The Appearance entry renders in the Settings sidebar only after the per-tenant `navigation.ts` entry is added (step 2).
26
+
27
+ ## Not handled by /git-sync
28
+
29
+ `/git-sync` does not author the per-tenant `navigation.ts` nav entry — it is project-owned business content and must be added by hand per tenant. `/git-sync` also will not retroactively restore the route for tenants that were previously stripped by the old delete special-case; run the prepared `/external sync --all` to apply the new non-deleting baseline.