@elevasis/sdk 1.5.3 → 1.5.4

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 (58) hide show
  1. package/dist/cli.cjs +899 -57
  2. package/dist/index.d.ts +94 -110
  3. package/package.json +3 -3
  4. package/reference/_navigation.md +11 -1
  5. package/reference/_reference-manifest.json +70 -0
  6. package/reference/claude-config/commands/submit-issue.md +12 -0
  7. package/reference/claude-config/hooks/post-edit-validate.mjs +109 -0
  8. package/reference/claude-config/hooks/tool-failure-recovery.mjs +73 -0
  9. package/reference/claude-config/rules/deployment.md +57 -0
  10. package/reference/claude-config/rules/docs.md +26 -0
  11. package/reference/claude-config/rules/error-handling.md +56 -0
  12. package/reference/claude-config/rules/execution.md +40 -0
  13. package/reference/claude-config/rules/frontend.md +43 -0
  14. package/reference/claude-config/rules/observability.md +31 -0
  15. package/reference/claude-config/rules/organization-os.md +62 -0
  16. package/reference/claude-config/rules/platform.md +41 -0
  17. package/reference/claude-config/rules/shared-types.md +46 -0
  18. package/reference/claude-config/rules/task-tracking.md +47 -0
  19. package/reference/claude-config/scripts/statusline-command.js +18 -0
  20. package/reference/claude-config/settings.json +30 -0
  21. package/reference/claude-config/skills/deploy/SKILL.md +166 -0
  22. package/reference/claude-config/skills/dsp/SKILL.md +66 -0
  23. package/reference/claude-config/skills/elevasis/SKILL.md +239 -0
  24. package/reference/claude-config/skills/explore/SKILL.md +78 -0
  25. package/reference/claude-config/skills/project/SKILL.md +918 -0
  26. package/reference/claude-config/skills/save/SKILL.md +197 -0
  27. package/reference/claude-config/skills/setup/SKILL.md +210 -0
  28. package/reference/claude-config/skills/status/SKILL.md +60 -0
  29. package/reference/claude-config/skills/submit-issue/SKILL.md +179 -0
  30. package/reference/claude-config/skills/sync/SKILL.md +81 -0
  31. package/reference/cli.mdx +19 -4
  32. package/reference/deployment/provided-features.mdx +24 -2
  33. package/reference/framework/agent.mdx +12 -4
  34. package/reference/framework/project-structure.mdx +9 -3
  35. package/reference/packages/core/src/README.md +1 -1
  36. package/reference/packages/core/src/business/README.md +52 -0
  37. package/reference/packages/core/src/organization-model/README.md +25 -26
  38. package/reference/packages/ui/src/app/README.md +24 -0
  39. package/reference/platform-tools/type-safety.mdx +0 -10
  40. package/reference/scaffold/core/organization-graph.mdx +37 -28
  41. package/reference/scaffold/core/organization-model.mdx +34 -36
  42. package/reference/scaffold/index.mdx +1 -0
  43. package/reference/scaffold/operations/propagation-pipeline.md +7 -3
  44. package/reference/scaffold/operations/scaffold-maintenance.md +2 -2
  45. package/reference/scaffold/operations/workflow-recipes.md +18 -1
  46. package/reference/scaffold/recipes/add-a-feature.md +37 -21
  47. package/reference/scaffold/recipes/add-a-resource.md +4 -2
  48. package/reference/scaffold/recipes/customize-organization-model.md +400 -0
  49. package/reference/scaffold/recipes/extend-a-base-entity.md +140 -0
  50. package/reference/scaffold/recipes/gate-by-feature-or-admin.md +18 -12
  51. package/reference/scaffold/recipes/index.md +3 -3
  52. package/reference/scaffold/reference/contracts.md +11 -32
  53. package/reference/scaffold/reference/feature-registry.md +10 -9
  54. package/reference/scaffold/reference/glossary.md +14 -18
  55. package/reference/scaffold/ui/customization.md +2 -2
  56. package/reference/scaffold/ui/feature-flags-and-gating.md +40 -54
  57. package/reference/scaffold/ui/feature-shell.mdx +22 -23
  58. package/reference/scaffold/ui/recipes.md +118 -3
@@ -0,0 +1,918 @@
1
+ ---
2
+ name: project
3
+ description: "Portfolio- and project-level work management -- orientation, intent routing, active projects, milestones, tasks, notes, and resume context -- via the elevasis-sdk project:* CLI."
4
+ argument-hint: "[create | list | work | add | update | status | note | milestone | task | delete] [args]"
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
6
+ ---
7
+
8
+ # Project Management (Portfolio + Per-Project)
9
+
10
+ `/project` is the primary work-tracking entrypoint for the template. It covers:
11
+
12
+ - **Portfolio orientation** — bare `/project` invocation shows the landscape of active work and suggests next actions.
13
+ - **Intent routing** — on an opening message that reads as "do work", decide new-vs-resume and route accordingly.
14
+ - **New-work flow** — when the user starts multi-step work without a project, ask: create project, link existing, or standalone.
15
+ - **CRUD surface** — projects, milestones, tasks, notes, checklists via `elevasis-sdk project:*`.
16
+
17
+ > **Note:** the template no longer ships a separate `/work` skill. Project tasks are the unit of work; use `/project task:*` operations for task lifecycle. Resume context is canonical in `prj_tasks.resume_context` and written via `project:task:save` (never via task-doc frontmatter).
18
+
19
+ **Usage:**
20
+
21
+ - `/project` — **Portfolio orientation** (see "Orientation Mode" below). List active/blocked projects, surface most-recently-touched project's `resume_context`, suggest next actions.
22
+ - `/project list` — Same as no-args orientation but just the project table, no suggestions.
23
+ - `/project work <query>` — Fuzzy-match a project/task and print a resume brief (wraps `project:work`).
24
+ - `/project status [<client>]` — Detailed status across all projects, or a single project.
25
+ - `/project create` — Guided project creation (QnA walkthrough).
26
+ - `/project add "Client Name" [--status active] [--value 5000]` — Quick create (flags only, no QnA).
27
+ - `/project update <client> --status on_track` — Update project fields.
28
+ - `/project milestone add <client> "Phase 1" [--due 2026-05-01]` — Add milestone.
29
+ - `/project milestone update <client> "Phase 1" --status completed` — Update milestone.
30
+ - `/project task add <client> "API docs" --milestone "Phase 1" [--type documentation]` — Add task.
31
+ - `/project task update <client> "API docs" --status approved` — Update task.
32
+ - `/project task save <task> --current-state "..."` — Persist `resume_context` (use this, never task-doc frontmatter).
33
+ - `/project note <client> "Kickoff call went well" [--type call_note]` — Add note.
34
+ - `/project notes <client>` — List notes for project.
35
+ - `/project checklist <client> "<milestone>"` — View checklist for a milestone.
36
+ - `/project delete <client>` — Delete project (cascades milestones, tasks, notes).
37
+
38
+ ---
39
+
40
+ ## Orientation Mode (bare `/project` invocation)
41
+
42
+ When invoked without a subcommand, enter **project mode**: present the portfolio landscape and offer next actions. This is the hub — distinct from `project:work <id>`, which is single-task resume.
43
+
44
+ ### Flow
45
+
46
+ 1. **List active work** — run:
47
+
48
+ ```bash
49
+ pnpm -C operations exec elevasis-sdk project:list --status active,blocked --format brief
50
+ ```
51
+
52
+ Show a compact table: client, status, last-touched.
53
+
54
+ 2. **Surface most-recently-touched project's resume context** — identify the top row (most recent `updated_at`), then print its latest task's `resume_context` (via `project:task:list` → pick most recent in-progress task → `project:task:resume <id> --pretty`). Keep it short: current state + next steps, no files dump.
55
+
56
+ 3. **List available operations** — a one-liner reminder of what the user can do from here:
57
+
58
+ ```
59
+ Available: /project status <client> | /project work <query> | /project task add | /project note | /project create
60
+ ```
61
+
62
+ 4. **Offer next-action suggestions** — 1-3 concrete follow-ups driven by what's on screen. Examples:
63
+ - "3 active projects, 1 blocked (Acme — waiting on credentials). Resume Beta (most recent)?"
64
+ - "No active projects. Create one with `/project create`?"
65
+ - "Acme's Phase 2 has 2 overdue tasks. Open status?"
66
+
67
+ ### Presentation template
68
+
69
+ ```
70
+ Project Portfolio (2 active, 1 blocked)
71
+ =======================================
72
+ | Client | Status | Last touched |
73
+ |--------------|----------|--------------|
74
+ | Beta LLC | on_track | 2h ago |
75
+ | Acme Corp | blocked | 1d ago |
76
+ | Gamma Inc | active | 4d ago |
77
+
78
+ Most recent: Beta LLC — API integration
79
+ Current: Endpoint wired, tests passing locally.
80
+ Next: Deploy to staging, verify webhook delivery.
81
+
82
+ Next? Resume Beta | Status Acme (why blocked?) | Create new project
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Intent Detection (opening-message routing)
88
+
89
+ Apply this heuristic on the user's first substantive message of a session, before branching into any other operation. The goal: distinguish **resume existing work** from **start new work**, and confirm before committing.
90
+
91
+ ### Signals → classification
92
+
93
+ | Signal in opening message | Classify as |
94
+ | ----------------------------------------------------------------------------------------------- | ---------------------------------- |
95
+ | References a specific file path, PR, commit, or existing task/milestone/project by name | **Resume** |
96
+ | "Continue", "pick up", "finish", "the thing we were doing", "yesterday's work" | **Resume** |
97
+ | "Let's build X", "new Y", "I want to add Z", "start a new project", "help me with a new client" | **New work** |
98
+ | Single-file cosmetic ask: "fix typo in X", "rename Y", "update dep Z" | **Trivial** (skip new-work prompt) |
99
+ | Ambiguous / discussion only | Ask before routing |
100
+
101
+ ### Routing
102
+
103
+ - **Resume** — run `project:work <query>` with the extracted entity (file path stem, project name, task keywords). If one clean match, print the brief and ask "Continue here?". If multiple matches, show top 3 and ask which. If zero matches, fall back to orientation mode with a note ("No match for 'acme webhook'; here's the landscape").
104
+ - **New work** — enter the **New-Work Project Decision** flow (next section).
105
+ - **Trivial** — proceed directly; do not prompt about projects. Small single-file edits don't need portfolio tracking.
106
+ - **Ambiguous** — reply with orientation mode output and ask "Resume something, or start new?"
107
+
108
+ **Always confirm before branching.** A misclassified "new" routed as "resume" burns trust faster than a one-line confirmation.
109
+
110
+ ---
111
+
112
+ ## New-Work Project Decision
113
+
114
+ When intent detection classifies the opening ask as **new multi-step work** and the conversation has no established project context, ask this question before writing any code:
115
+
116
+ ```
117
+ Scope this work under a project?
118
+ a) Create new project "<proposed-slug>" (recommended for multi-step work)
119
+ b) Link to existing "<closest-match>" (if fuzzy-search finds one)
120
+ c) Standalone — no project tracking (one-off / trivial)
121
+ ```
122
+
123
+ ### Rules
124
+
125
+ - **Default to (a)** when the ask is multi-step (multiple files, multiple sessions expected, client-facing deliverable).
126
+ - **Offer (b)** only when `project:list` fuzzy-matches produce a plausible candidate (name similarity, shared entity references). If nothing matches, omit the option — do not invent one.
127
+ - **Skip the prompt entirely** for trivial single-file edits — intent detection's "Trivial" branch handles this.
128
+ - **Propose a slug** by extracting the core noun from the ask. "Build a lead scraper for Acme" → `acme-lead-scraper`. User can override.
129
+
130
+ ### After the decision
131
+
132
+ - **(a) Create** — invoke the guided `/project create` QnA flow (see below), pre-filling the name/description from the ask.
133
+ - **(b) Link** — run `project:resolve <query>` to confirm the match, then add a task to that project for the new work via `project:task:create`.
134
+ - **(c) Standalone** — proceed without project tracking. Do not create orphan task docs; standalone work leaves no artifact.
135
+
136
+ ---
137
+
138
+ ## Connection
139
+
140
+ ### Environment
141
+
142
+ ```bash
143
+ # .env (project root)
144
+ ELEVASIS_PLATFORM_KEY=sk_...
145
+ ```
146
+
147
+ `ELEVASIS_PLATFORM_KEY` is read from the environment automatically. The SDK CLI walks up
148
+ directories to find `.env`, so it resolves correctly from both the project root and
149
+ `operations/`. `ELEVASIS_API_URL` defaults to `https://api.elevasis.io` (production). Set
150
+ `ELEVASIS_API_URL=http://localhost:5170` to target a local API instance, or set
151
+ `NODE_ENV=development` if the SDK CLI respects that convention.
152
+
153
+ No `--prod` flag is needed — the template targets production by default via `ELEVASIS_API_URL`.
154
+
155
+ ### CLI Invocation
156
+
157
+ All project operations go through the `elevasis-sdk` CLI installed in `operations/`. Run every
158
+ command from the template project root using `-C operations`:
159
+
160
+ ```bash
161
+ pnpm -C operations exec elevasis-sdk project:<command> [args]
162
+ ```
163
+
164
+ Organization scoping is handled server-side via `ELEVASIS_PLATFORM_KEY`. No org header or
165
+ `--org` flag is required.
166
+
167
+ ---
168
+
169
+ ## Database Schema
170
+
171
+ ### Tables
172
+
173
+ | Table | Purpose | Key Columns |
174
+ | ---------------- | ---------------------------- | --------------------------------------------------------------------- |
175
+ | `prj_projects` | Client projects/contracts | name, kind, status, description, contract_value, start/end dates |
176
+ | `prj_milestones` | Phases within projects | name, status, due_date, sequence, completed_at, checklist |
177
+ | `prj_tasks` | Work items within milestones | name, status, type, due_date, milestone_id, resume_context, checklist |
178
+ | `prj_notes` | Meeting notes, updates | type, content, summary, occurred_at, task_id, milestone_id |
179
+
180
+ ### Project Kind
181
+
182
+ | Kind | Description |
183
+ | ------------------- | -------------------------------- |
184
+ | `client_engagement` | External client delivery project |
185
+ | `internal` | Internal project work |
186
+ | `research` | Research and investigation |
187
+ | `other` | Catch-all |
188
+
189
+ Default filter for `/project` operations is `kind=client_engagement` unless the user's intent
190
+ is clearly internal or `--kind` is specified explicitly.
191
+
192
+ ### Status Values
193
+
194
+ | Entity | Values |
195
+ | --------- | ------------------------------------------------------------------------------------------------------------------------ |
196
+ | Project | `active`, `on_track`, `at_risk`, `blocked`, `completed`, `paused` |
197
+ | Milestone | `upcoming`, `in_progress`, `completed`, `overdue`, `blocked` |
198
+ | Task | `planned`, `in_progress`, `blocked`, `completed`, `cancelled`, `submitted`, `approved`, `rejected`, `revision_requested` |
199
+ | Note type | `call_note`, `status_update`, `issue`, `blocker`, `agent_learning` |
200
+ | Task type | `documentation`, `code`, `report`, `design`, `refactor`, `feature`, `bug`, `research`, `other` |
201
+
202
+ ### Checklist Shape
203
+
204
+ Both `prj_milestones.checklist` and `prj_tasks.checklist` store a JSONB array of objects with this shape:
205
+
206
+ ```json
207
+ [
208
+ { "id": "uuid", "label": "Item label", "completed": false },
209
+ { "id": "uuid", "label": "Another item", "completed": true }
210
+ ]
211
+ ```
212
+
213
+ 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:
214
+
215
+ 1. Read the current checklist (via psql or `project:task:get` / `project:milestone:list`)
216
+ 2. Mutate the array in memory (append, flip `completed`, filter out)
217
+ 3. Write the entire array back via `--checklist '<json>'`
218
+
219
+ To clear a checklist: `--checklist '[]'`.
220
+
221
+ ### Foreign Keys
222
+
223
+ - `prj_milestones.project_id` → `prj_projects.id` (CASCADE)
224
+ - `prj_tasks.project_id` → `prj_projects.id` (CASCADE)
225
+ - `prj_tasks.milestone_id` → `prj_milestones.id` (SET NULL)
226
+ - `prj_tasks.parent_task_id` → `prj_tasks.id` (SET NULL) — for subtasks
227
+ - `prj_notes.project_id` → `prj_projects.id` (CASCADE)
228
+ - `prj_notes.task_id` → `prj_tasks.id` (SET NULL)
229
+ - `prj_notes.milestone_id` → `prj_milestones.id` (SET NULL)
230
+ - `prj_projects.deal_id` → `acq_deals.id` (SET NULL)
231
+ - `prj_projects.client_company_id` → `acq_companies.id` (SET NULL)
232
+
233
+ ---
234
+
235
+ ## Operations
236
+
237
+ ### `list` — Portfolio Table (no orientation extras)
238
+
239
+ For a plain project table without resume context or next-action suggestions (use the bare `/project` orientation mode above when the user wants the full hub experience):
240
+
241
+ ```bash
242
+ pnpm -C operations exec elevasis-sdk project:list --kind client_engagement --pretty
243
+ ```
244
+
245
+ Present as:
246
+
247
+ ```
248
+ Project Portfolio
249
+ =================
250
+ | Client | Status | Kind | Value |
251
+ |--------------------|----------|--------------------|---------|
252
+ | Acme Corp | on_track | client_engagement | $5,000 |
253
+ | Beta LLC | active | client_engagement | $3,500 |
254
+ ```
255
+
256
+ For progress detail (milestones/tasks), follow up with `project:milestone:list` and
257
+ `project:task:list` per project.
258
+
259
+ ### `work <query>` — Resume Brief
260
+
261
+ Wraps `project:work` for fuzzy-matched resume. Used by intent-detection "resume" classification.
262
+
263
+ ```bash
264
+ pnpm -C operations exec elevasis-sdk project:work <query> --pretty
265
+ ```
266
+
267
+ Prints the matched project/task brief with current `resume_context`. If multiple matches, show top 3 and ask which.
268
+
269
+ ### `status [<client>]` — Detailed Status
270
+
271
+ If client specified, show full detail for that project. If not, show all.
272
+
273
+ **Resolve the project first** (see Client Inference below), then:
274
+
275
+ ```bash
276
+ # Get project details
277
+ pnpm -C operations exec elevasis-sdk project:get <project-id>
278
+
279
+ # Milestones (ordered by sequence)
280
+ pnpm -C operations exec elevasis-sdk project:milestone:list --project <project-id> --pretty
281
+
282
+ # Tasks (grouped by milestone)
283
+ pnpm -C operations exec elevasis-sdk project:task:list --project <project-id> --pretty
284
+
285
+ # Recent notes
286
+ pnpm -C operations exec elevasis-sdk project:note:list --project <project-id> --pretty
287
+ ```
288
+
289
+ Present as:
290
+
291
+ ```
292
+ Acme Corp — On Track
293
+ =====================
294
+ Description: Automation project for AI-powered workflows
295
+ Contract: $5,000 | Started: 2026-04-01 | Target: 2026-06-01
296
+
297
+ Milestones (2/4 complete)
298
+ [x] Phase 1: Discovery (completed)
299
+ [>] Phase 2: Implementation (in_progress, due 2026-05-01)
300
+ [ ] Phase 3: Testing (upcoming, due 2026-05-15)
301
+ [ ] Phase 4: Launch (upcoming, due 2026-06-01)
302
+
303
+ Tasks (3/8 approved)
304
+ Phase 2: Implementation
305
+ [approved] Requirements doc (documentation)
306
+ [in_progress] API integration (code, due 2026-05-01)
307
+ [planned] User guide (documentation)
308
+
309
+ Recent Notes
310
+ 2026-04-05 [call_note] Weekly check-in — on track, API work started
311
+ 2026-04-01 [call_note] Kickoff — confirmed scope and timeline
312
+ ```
313
+
314
+ ### `create` — Guided Project Creation (QnA Flow)
315
+
316
+ Interactive walkthrough that collects project details step by step using `AskUserQuestion`,
317
+ then creates the project, milestones, and kickoff note in one go.
318
+
319
+ **Step 1: Project basics**
320
+
321
+ Ask via `AskUserQuestion` (single question, free-text via "Other"):
322
+
323
+ ```
324
+ What's the project name and a brief description of the scope?
325
+ ```
326
+
327
+ The user will reply with something like "Acme Corp automation -- building a lead gen pipeline
328
+ with email outreach". Parse the name and description from the response.
329
+
330
+ **Step 2: Deal/company linking**
331
+
332
+ Search for matching records using read-only psql (the psql role is SELECT-only).
333
+
334
+ Note: `SUPABASE_READONLY_URL` must be set in the template `.env` for psql queries. If not
335
+ set, skip this step and advise the user to link via the Command Center UI after creation.
336
+
337
+ If `SUPABASE_READONLY_URL` is available, query using `<ORG_ID>` from the platform key's
338
+ associated organization (you can retrieve it via `project:list` output which includes
339
+ `organization_id`):
340
+
341
+ ```bash
342
+ source .env && psql "$SUPABASE_READONLY_URL" -c \
343
+ "SELECT id, name, domain FROM acq_companies WHERE organization_id = '<ORG_ID>' AND name ILIKE '%<parsed_name>%' ORDER BY updated_at DESC LIMIT 5;"
344
+
345
+ source .env && psql "$SUPABASE_READONLY_URL" -c \
346
+ "SELECT d.id, d.contact_email, d.cached_stage, c.name AS company_name
347
+ FROM acq_deals d
348
+ LEFT JOIN acq_contacts ct ON ct.id = d.contact_id
349
+ LEFT JOIN acq_companies c ON c.id = ct.company_id
350
+ WHERE d.organization_id = '<ORG_ID>'
351
+ AND (d.contact_email ILIKE '%<parsed_name>%' OR c.name ILIKE '%<parsed_name>%')
352
+ ORDER BY d.updated_at DESC LIMIT 5;"
353
+ ```
354
+
355
+ If matches found, ask via `AskUserQuestion`:
356
+
357
+ ```
358
+ Found matching records. Link this project?
359
+ - [Company: Acme Corp (acme.com)]
360
+ - [Deal: john@acme.com (closed_won)]
361
+ - No linking
362
+ ```
363
+
364
+ If no matches, skip silently.
365
+
366
+ **Step 3: Contract details**
367
+
368
+ Ask via `AskUserQuestion`:
369
+
370
+ ```
371
+ Contract details?
372
+ - Options with previews showing common structures:
373
+ - "Fixed project" -- one-time fee
374
+ - "Monthly retainer" -- recurring
375
+ - "Hourly" -- time & materials
376
+ - Other
377
+ ```
378
+
379
+ Then follow up for the value, start date, and target end date. These can be collected in a
380
+ single question:
381
+
382
+ ```
383
+ What's the contract value, start date, and target end date?
384
+ (e.g., "$5000, starting today, targeting June 1")
385
+ ```
386
+
387
+ Parse natural language dates ("today", "next Monday", "June 1") into ISO format.
388
+
389
+ **Step 4: Milestone suggestions**
390
+
391
+ Based on the project description from Step 1, suggest 3-5 milestones that fit the scope. Use
392
+ your understanding of the project to propose relevant phases.
393
+
394
+ **Guidelines for milestone suggestions:**
395
+
396
+ - For automation/integration projects: Discovery, Implementation, Testing, Launch
397
+ - For content/marketing projects: Strategy, Content Creation, Review, Distribution
398
+ - For consulting/advisory: Assessment, Recommendations, Implementation Support
399
+ - Always include a Discovery/Kickoff phase first and a Launch/Handoff phase last
400
+ - Suggest due dates spaced evenly between start and target end date
401
+
402
+ Present via `AskUserQuestion` with previews:
403
+
404
+ ```
405
+ Suggested milestones for "<project name>". Select which to include:
406
+ (multiSelect: true)
407
+
408
+ - Discovery (due <start + 2 weeks>)
409
+ - Implementation (due <midpoint>)
410
+ - Testing (due <end - 2 weeks>)
411
+ - Launch (due <end date>)
412
+ ```
413
+
414
+ The user can select which ones to keep, modify via "Other", or skip entirely.
415
+
416
+ **Step 5: Kickoff note**
417
+
418
+ Ask via `AskUserQuestion`:
419
+
420
+ ```
421
+ Add a kickoff note? This captures initial context (scope confirmed, key contacts, etc.)
422
+ - Yes, let me type one
423
+ - Skip for now
424
+ ```
425
+
426
+ If yes, collect the note content.
427
+
428
+ **Step 6: Execute**
429
+
430
+ Create everything in sequence using the CLI:
431
+
432
+ ```bash
433
+ # 1. Create project
434
+ pnpm -C operations exec elevasis-sdk project:create \
435
+ --name "<name>" \
436
+ --kind client_engagement \
437
+ --status active \
438
+ --description "<desc>"
439
+
440
+ # 2. Create milestones
441
+ pnpm -C operations exec elevasis-sdk project:milestone:create \
442
+ --project <project-id> \
443
+ --name "<milestone-name>" \
444
+ --status upcoming \
445
+ --due-date <date>
446
+
447
+ # 3. Create kickoff note (if provided)
448
+ pnpm -C operations exec elevasis-sdk project:note:create \
449
+ --project <project-id> \
450
+ --content "<note-content>" \
451
+ --type call_note
452
+ ```
453
+
454
+ If `--company` or `--deal` linking was confirmed, use `project:update` after creation:
455
+
456
+ ```bash
457
+ pnpm -C operations exec elevasis-sdk project:update <project-id> --description "<updated with link info>"
458
+ ```
459
+
460
+ (Note: company/deal linking fields are set via the API. If the CLI `project:update` command
461
+ doesn't expose `--client-company-id` or `--deal-id` directly, document the project ID and
462
+ advise the user to link via the Command Center UI.)
463
+
464
+ **Step 7: Summary**
465
+
466
+ Show the created project:
467
+
468
+ ```
469
+ Project Created
470
+ ===============
471
+ Name: Acme Corp Automation
472
+ Kind: client_engagement
473
+ Status: active
474
+ Timeline: 2026-04-07 → 2026-06-01
475
+
476
+ Milestones:
477
+ 1. Discovery (upcoming, due 2026-04-21)
478
+ 2. Implementation (upcoming, due 2026-05-08)
479
+ 3. Testing (upcoming, due 2026-05-22)
480
+ 4. Launch (upcoming, due 2026-06-01)
481
+
482
+ Kickoff Note: Confirmed scope -- lead gen pipeline with email outreach.
483
+
484
+ Next: /project status acme
485
+ ```
486
+
487
+ ---
488
+
489
+ ### `add "<name>" [options]` — Quick Create Project (No QnA)
490
+
491
+ **Options:**
492
+
493
+ - `--status <status>` (default: `active`)
494
+ - `--value <number>` — contract value (informational, stored in description or notes)
495
+ - `--start <date>` — start date
496
+ - `--end <date>` — target end date
497
+ - `--description "<text>"` — scope description
498
+ - `--kind <kind>` (default: `client_engagement`)
499
+
500
+ ```bash
501
+ pnpm -C operations exec elevasis-sdk project:create \
502
+ --name "<name>" \
503
+ --kind client_engagement \
504
+ --status active \
505
+ --description "<desc>"
506
+ ```
507
+
508
+ **After creating:** Show the created project and suggest next steps (add milestones).
509
+
510
+ ### `update <client> [options]` — Update Project
511
+
512
+ **Options:** `--status`, `--name`, `--description`
513
+
514
+ First resolve the client (see Client Inference below), then:
515
+
516
+ ```bash
517
+ pnpm -C operations exec elevasis-sdk project:update <project-id> --status <status>
518
+ ```
519
+
520
+ ### `milestone add <client> "<name>" [options]` — Add Milestone
521
+
522
+ **Options:**
523
+
524
+ - `--status <status>` (default: `upcoming`)
525
+ - `--due <date>` — due date (ISO)
526
+ - `--description "<text>"`
527
+
528
+ ```bash
529
+ pnpm -C operations exec elevasis-sdk project:milestone:create \
530
+ --project <project-id> \
531
+ --name "<name>" \
532
+ --status upcoming \
533
+ --due-date <date>
534
+ ```
535
+
536
+ ### `milestone update <client> "<milestone>" [options]` — Update Milestone
537
+
538
+ Resolve milestone by name (see Client Inference for project resolution, then use
539
+ `project:milestone:list` to find the milestone ID by partial name match):
540
+
541
+ ```bash
542
+ # List milestones to find ID
543
+ pnpm -C operations exec elevasis-sdk project:milestone:list --project <project-id>
544
+
545
+ # Update status
546
+ pnpm -C operations exec elevasis-sdk project:milestone:update <milestone-id> --status completed
547
+
548
+ # Update checklist (full replace)
549
+ pnpm -C operations exec elevasis-sdk project:milestone:update <milestone-id> \
550
+ --checklist '[{"id":"uuid","label":"Item label","completed":false}]'
551
+ ```
552
+
553
+ If status changes to `completed`, the API auto-sets `completed_at`.
554
+
555
+ **Options:** `--status`, `--due-date`, `--name`, `--checklist <json>`
556
+
557
+ **Checklist mutations:** The CLI performs a full replace. To add, toggle, or remove an item:
558
+
559
+ 1. Read the current checklist via psql or `project:milestone:list`
560
+ 2. Mutate the array in memory
561
+ 3. Write back the full array via `--checklist '<json>'`
562
+
563
+ ### `checklist <client> "<milestone>"` — View Checklist
564
+
565
+ Resolve the milestone, then read its `checklist` JSONB column via read-only psql.
566
+
567
+ Note: Requires `SUPABASE_READONLY_URL` in the template `.env`. If not set, advise the user
568
+ to view the checklist via the Command Center UI, or add `SUPABASE_READONLY_URL` to `.env`.
569
+
570
+ ```bash
571
+ source .env && psql "$SUPABASE_READONLY_URL" -c \
572
+ "SELECT m.name, m.checklist
573
+ FROM prj_milestones m
574
+ WHERE m.project_id = '<project_id>' AND m.name ILIKE '%<name>%'
575
+ LIMIT 1;"
576
+ ```
577
+
578
+ The `checklist` column is a JSONB array of objects:
579
+
580
+ ```json
581
+ [
582
+ { "id": "uuid", "label": "Set up dev environment", "completed": true },
583
+ { "id": "uuid", "label": "Draft scope document", "completed": false }
584
+ ]
585
+ ```
586
+
587
+ Present as:
588
+
589
+ ```
590
+ Onboarding & Scope — Checklist (2/3 complete)
591
+ [x] Set up dev environment
592
+ [x] Schedule kickoff call
593
+ [ ] Draft scope document
594
+ ```
595
+
596
+ ### `task add <client> "<name>" [options]` — Add Task
597
+
598
+ **Options:**
599
+
600
+ - `--milestone "<name>"` — link to a milestone (resolve by name first)
601
+ - `--status <status>` (default: `planned`)
602
+ - `--type <type>` (default: `other`)
603
+ - `--due <date>`
604
+ - `--description "<text>"`
605
+ - `--checklist <json>` — initial checklist items
606
+
607
+ ```bash
608
+ # Resolve milestone ID first if --milestone provided
609
+ pnpm -C operations exec elevasis-sdk project:milestone:list --project <project-id>
610
+
611
+ # Create task
612
+ pnpm -C operations exec elevasis-sdk project:task:create \
613
+ --project <project-id> \
614
+ --title "<name>" \
615
+ --status planned \
616
+ --type <type> \
617
+ --milestone <milestone-id>
618
+
619
+ # Create task with initial checklist
620
+ pnpm -C operations exec elevasis-sdk project:task:create \
621
+ --project <project-id> \
622
+ --title "<name>" \
623
+ --checklist '[{"id":"1","label":"Step one","completed":false}]'
624
+ ```
625
+
626
+ ### `task update <client> "<task>" [options]` — Update Task
627
+
628
+ Resolve task by name within the project using `project:task:list`, then update by positional ID:
629
+
630
+ ```bash
631
+ # Find the task ID
632
+ pnpm -C operations exec elevasis-sdk project:task:list --project <project-id>
633
+
634
+ # Update status (positional <id> comes first, then flags)
635
+ pnpm -C operations exec elevasis-sdk project:task:update <task-id> --status <status>
636
+
637
+ # Update checklist (full replace)
638
+ pnpm -C operations exec elevasis-sdk project:task:update <task-id> \
639
+ --checklist '[{"id":"uuid","label":"Step","completed":false}]'
640
+
641
+ # Clear checklist
642
+ pnpm -C operations exec elevasis-sdk project:task:update <task-id> --checklist '[]'
643
+ ```
644
+
645
+ **Options:** `--status`, `--title`, `--milestone`, `--description`, `--checklist <json>`
646
+
647
+ **Important:** The task ID is a **positional argument** — it comes immediately after `project:task:update`, before any flags. There is no `--task-id` flag.
648
+
649
+ If status changes to `approved`, the API auto-sets `completed_at`.
650
+
651
+ **Checklist mutations:** Same full-replace semantics as milestones. To add, toggle, or remove an item:
652
+
653
+ 1. Read the current task via `project:task:get <task-id>`
654
+ 2. Mutate the checklist array in memory
655
+ 3. Write back the full array via `project:task:update <task-id> --checklist '<json>'`
656
+
657
+ ### `note <client> "<content>" [options]` — Add Note
658
+
659
+ **Options:**
660
+
661
+ - `--type <type>` (default: `call_note`) — see Note Type Selection below
662
+ - `--task <task-id>` — attach to a specific task (UUID)
663
+ - `--milestone <milestone-id>` — attach to a milestone (UUID)
664
+
665
+ ```bash
666
+ pnpm -C operations exec elevasis-sdk project:note:create \
667
+ --project <project-id> \
668
+ --content "<content>" \
669
+ --type <type>
670
+
671
+ # Attach to a task
672
+ pnpm -C operations exec elevasis-sdk project:note:create \
673
+ --project <project-id> \
674
+ --content "<content>" \
675
+ --type agent_learning \
676
+ --task <task-id>
677
+ ```
678
+
679
+ ### `notes <client>` — List Notes
680
+
681
+ ```bash
682
+ pnpm -C operations exec elevasis-sdk project:note:list --project <project-id> --pretty
683
+ ```
684
+
685
+ ### `delete <client>` — Delete Project
686
+
687
+ **ALWAYS confirm before deleting.** Show what will be deleted (milestone count, task count,
688
+ note count) using the list commands, then ask for confirmation.
689
+
690
+ ```bash
691
+ pnpm -C operations exec elevasis-sdk project:delete <project-id>
692
+ ```
693
+
694
+ Cascade deletes all milestones, tasks, and notes.
695
+
696
+ ---
697
+
698
+ ## Notes Management
699
+
700
+ Notes (`prj_notes`) are the durable record of project-scoped signals — conversation outcomes, blockers, status updates, and agent-captured learnings. They complement `resume_context` (which is task-scoped, temporal, and agent-facing) by providing a human-readable audit trail.
701
+
702
+ ### When to Create a Note vs. Fall Through to Global Auto-Memory
703
+
704
+ **Create a project note** when all of the following hold:
705
+
706
+ - A specific project and (optionally) task is in scope in the current session
707
+ - The content is project-bound — it would only matter to someone working on this project
708
+ - The content is durable — it should be visible in future status views, not just the current session
709
+
710
+ **Fall through to global auto-memory** when:
711
+
712
+ - No active project or task can be resolved from session context (see Project-Scope Resolution below)
713
+ - The content is cross-project or platform-wide (e.g., a general TypeScript pattern, a reusable workflow insight)
714
+ - The signal is ephemeral and not worth a DB write (e.g., "reminder: run linter before committing")
715
+
716
+ When in doubt and no project context is resolvable, global auto-memory is the safe default.
717
+
718
+ ### Note Type Selection Guide
719
+
720
+ | Type | Use when |
721
+ | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
722
+ | `call_note` | Transcribing or summarizing a live client / stakeholder call. Include key decisions and action items. |
723
+ | `status_update` | Milestone-level progress worth flagging to a human operator: phase complete, substantial deliverable, direction change. Don't emit one every session turn. |
724
+ | `issue` | Bug, regression, unexpected failure, contract mismatch. Include reproduction context. |
725
+ | `blocker` | Work cannot proceed without external action: decision needed, credential missing, upstream fix required. |
726
+ | `agent_learning` | Project-bound knowledge the agent discovered: API quirks, client conventions, deploy gotchas, rate limits. Captures "things a future agent resuming this project should know" so it travels with the project instead of living only in global auto-memory. |
727
+
728
+ ### Project-Scope Resolution
729
+
730
+ Before writing a note, the agent resolves which project (and optionally task) to attach it to:
731
+
732
+ 1. **Explicit in session** — a project/task UUID was mentioned or returned by a recent `project:work <id>` or `project:task:*` invocation in this session. Use it directly.
733
+ 2. **Implicit from task list** — if step 1 yields nothing, run:
734
+
735
+ ```bash
736
+ pnpm -C operations exec elevasis-sdk project:list --status active,blocked --format brief
737
+ pnpm -C operations exec elevasis-sdk project:task:list --project <top-project-id> --status in_progress
738
+ ```
739
+
740
+ Use the most-recently-touched project's in-progress task if there is exactly one. If multiple in-progress tasks exist, prefer the one that most closely matches the current conversation topic.
741
+
742
+ 3. **Prompt the user** — if steps 1 and 2 are both ambiguous or empty, ask once: "Which project should I attach this note to? (project UUID or slug, or 'skip' to use global auto-memory)."
743
+
744
+ 4. **Fall through** — if the user says "skip" or no resolution is possible, write to global auto-memory and continue.
745
+
746
+ Resolution is **agent-side at call time** — there is no middleware or automatic routing layer. The agent infers context from the session.
747
+
748
+ ### Agent Workflow: Capturing an `agent_learning`
749
+
750
+ When the agent recognizes a project-scoped learning (an API quirk, an undocumented constraint, a client convention discovered during implementation):
751
+
752
+ 1. Recognize the signal — e.g., "Apify actor X rate-limits at 20 rps", "client requires ISO dates, not timestamps", "staging env needs VPN before webhook delivery works"
753
+ 2. Resolve active project and task from session context (see above)
754
+ 3. Write the note:
755
+
756
+ ```bash
757
+ pnpm -C operations exec elevasis-sdk project:note:create \
758
+ --project <project-id> \
759
+ --type agent_learning \
760
+ --task <task-id> \
761
+ --content "<concise, factual statement of what was learned>"
762
+ ```
763
+
764
+ Omit `--task` if no specific task is in scope (e.g., the learning is milestone-level or project-level).
765
+
766
+ 4. If no project can be resolved, write the learning to global auto-memory instead.
767
+
768
+ **Content style for `agent_learning` notes:** write as a factual assertion another agent could act on — "Apify actor X rate-limits at 20 rps; add a 50ms delay between calls" rather than "I noticed that Apify seems slow." Keep it under 200 characters when possible.
769
+
770
+ ---
771
+
772
+ ## Status Transitions from Other Skills
773
+
774
+ The `/project` skill is the canonical reference for how lifecycle signals from other skills map to `project:task:update` status transitions. The behavioral hooks live in the emitting skills; this section documents the contract.
775
+
776
+ ### Transition Map
777
+
778
+ | Signal | Source skill | Transition | CLI call |
779
+ | ---------------------------------------- | -------------- | -------------------------------------- | -------------------------------------------------- |
780
+ | Successful `git push` via `/deploy` | `deploy/` | linked task → `submitted` | `project:task:update <task-id> --status submitted` |
781
+ | `/save` catches "I'm stuck" / blocker | `save/` | linked task → `blocked` + blocker note | `project:task:update <task-id> --status blocked` |
782
+ | User/agent says "I'm done" / "task done" | `/project` NLM | active task → `completed` | `project:task:update <task-id> --status completed` |
783
+
784
+ ### "I'm Done" Recognition (Natural Language Mode)
785
+
786
+ When the user or agent says any of the following in the context of a project task, treat it as a `completed` transition signal:
787
+
788
+ - "I'm done", "I'm finished", "done with this", "that's done"
789
+ - "task complete", "task finished", "mark as complete"
790
+ - "wrap this up", "close this task", "finalize this"
791
+
792
+ Resolve the active task from session context (see Project-Scope Resolution), confirm once ("Mark `<task name>` as completed?"), then fire:
793
+
794
+ ```bash
795
+ pnpm -C operations exec elevasis-sdk project:task:update <task-id> --status completed
796
+ ```
797
+
798
+ If no task resolves, ask the user which task to complete rather than silently skipping.
799
+
800
+ ### Transition Rules (All Skills)
801
+
802
+ These rules apply to every skill that emits a transition:
803
+
804
+ - **Explicit task ID only** — use the UUID resolved from session context. Never guess.
805
+ - **Best-effort** — if the CLI returns non-2xx, emit a warning line and continue. Do not block the primary operation.
806
+ - **Idempotent** — if the task is already in the target status, the update is a no-op. Fire it anyway.
807
+ - **Confirm before `completed`** — always ask once before marking a task done, since this is hard to undo semantically.
808
+
809
+ For full implementation details, see the emitting skills: `deploy/SKILL.md` (Step 8) and `save/SKILL.md` (Steps 5, 5a).
810
+
811
+ ---
812
+
813
+ ## Client Inference
814
+
815
+ Resolve which project the user means using these rules (in priority order):
816
+
817
+ 1. **Exact ID** — if the argument looks like a UUID, use it directly with `project:get`
818
+ 2. **Name match** — list projects filtered by `client_engagement` kind, then match by name:
819
+ ```bash
820
+ pnpm -C operations exec elevasis-sdk project:list --kind client_engagement
821
+ ```
822
+ Filter results by partial name match against the user's input (case-insensitive).
823
+ 3. **Single active project** — if only one non-completed `client_engagement` project exists,
824
+ use it without asking
825
+ 4. **Context from conversation** — if the conversation has been discussing a specific client,
826
+ use that one
827
+ 5. **Ambiguous** — if multiple match or none match, list projects and ask
828
+
829
+ ---
830
+
831
+ ## Natural Language Mode
832
+
833
+ When args don't match any command pattern, infer intent from natural language:
834
+
835
+ | User says | Inferred operation |
836
+ | -------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
837
+ | "how's acme doing" | `status acme` |
838
+ | "add a note: weekly call, everything on track" | `note <active-project> "weekly call, everything on track"` |
839
+ | "mark phase 2 complete for acme" | `milestone update acme "phase 2" --status completed` |
840
+ | "approve the API docs task" | `task update <project> "API docs" --status approved` |
841
+ | "new client: Beta LLC, $3500/mo, starting may 1" | `add "Beta LLC" --value 3500 --start 2026-05-01` |
842
+ | "what's overdue?" | List milestones where `due_date < now() AND status != 'completed'` |
843
+ | "block acme, waiting on client credentials" | `update acme --status blocked` |
844
+ | "show checklist for phase 2" | Read and display checklist for milestone "phase 2" via psql or `project:milestone:list` |
845
+ | "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>'` |
846
+ | "mark 'deploy staging' done on task X" | Read task X's checklist → flip `completed` on matching item → `project:task:update <id> --checklist '<json>'` |
847
+ | "clear the checklist on task X" | `project:task:update <task-id> --checklist '[]'` |
848
+ | "add checklist item to onboarding milestone: review scope doc" | Read milestone checklist → append item → `project:milestone:update <id> --checklist '<json>'` |
849
+ | "I'm done" / "task complete" / "done with this" | Resolve active task → confirm → `project:task:update <task-id> --status completed` |
850
+ | "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"` |
851
+ | "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"` |
852
+
853
+ **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.
854
+
855
+ ---
856
+
857
+ ## Bulk Operations
858
+
859
+ ### Add Multiple Milestones
860
+
861
+ For creating a standard milestone set, run `project:milestone:create` in sequence:
862
+
863
+ ```bash
864
+ for name in "Discovery" "Implementation" "Testing" "Launch"; do
865
+ pnpm -C operations exec elevasis-sdk project:milestone:create \
866
+ --project <project-id> \
867
+ --name "$name" \
868
+ --status upcoming
869
+ done
870
+ ```
871
+
872
+ ### Overdue Report
873
+
874
+ Query via read-only psql for milestones past their due date. Requires `SUPABASE_READONLY_URL`
875
+ in the template `.env`. Replace `<ORG_ID>` with the organization ID associated with your
876
+ `ELEVASIS_PLATFORM_KEY` (visible in `project:list` output as `organization_id`). If
877
+ `SUPABASE_READONLY_URL` is not configured, use `project:milestone:list` per project and filter
878
+ manually.
879
+
880
+ ```bash
881
+ source .env && psql "$SUPABASE_READONLY_URL" -c \
882
+ "SELECT
883
+ p.name AS project,
884
+ m.name AS milestone,
885
+ m.due_date,
886
+ m.status,
887
+ (CURRENT_DATE - m.due_date::date) AS days_overdue
888
+ FROM prj_milestones m
889
+ JOIN prj_projects p ON p.id = m.project_id
890
+ WHERE p.organization_id = '<ORG_ID>'
891
+ AND m.due_date < CURRENT_DATE
892
+ AND m.status NOT IN ('completed')
893
+ ORDER BY m.due_date;"
894
+ ```
895
+
896
+ ---
897
+
898
+ ## Safety Rules
899
+
900
+ 1. **Always confirm deletes** — show what will be cascade-deleted before executing
901
+ 2. **Organization scoping** — all API calls are automatically org-scoped via
902
+ `ELEVASIS_PLATFORM_KEY`; every direct psql query MUST include an `organization_id` filter
903
+ (use `<ORG_ID>` as a placeholder and confirm the value with the user if unknown)
904
+ 3. **Read before write** — when updating, show current state before applying changes
905
+ 4. **Validate status values** — reject invalid status strings before sending to the CLI
906
+ 5. **Kind default** — default to `--kind client_engagement` when user intent is client
907
+ delivery; use `--kind internal` for internal project work
908
+ 6. **Template project assumption** — the template is a single-organization project. All
909
+ `/project` operations operate within the organization scoped by `ELEVASIS_PLATFORM_KEY`.
910
+ There is no cross-org capability.
911
+ 7. **Checklist full-replace** — the `--checklist` flag replaces the entire array. Always read
912
+ the current checklist before writing to avoid losing existing items.
913
+ 8. **Confirm task completion** — always ask once before marking a task `completed` via "I'm done"
914
+ recognition. This status is semantically significant and warrants a confirmation step.
915
+
916
+ ---
917
+
918
+ **Last Updated:** 2026-04-19