@elevasis/sdk 0.5.13 → 0.5.15

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/index.d.ts CHANGED
@@ -2436,7 +2436,11 @@ type Database = {
2436
2436
  };
2437
2437
  sessions: {
2438
2438
  Row: {
2439
+ context_window_size: number;
2439
2440
  created_at: string | null;
2441
+ cumulative_input_tokens: number;
2442
+ cumulative_output_tokens: number;
2443
+ deleted_at: string | null;
2440
2444
  ended_at: string | null;
2441
2445
  memory_snapshot: Json;
2442
2446
  metadata: Json | null;
@@ -2448,7 +2452,11 @@ type Database = {
2448
2452
  user_id: string | null;
2449
2453
  };
2450
2454
  Insert: {
2455
+ context_window_size?: number;
2451
2456
  created_at?: string | null;
2457
+ cumulative_input_tokens?: number;
2458
+ cumulative_output_tokens?: number;
2459
+ deleted_at?: string | null;
2452
2460
  ended_at?: string | null;
2453
2461
  memory_snapshot: Json;
2454
2462
  metadata?: Json | null;
@@ -2460,7 +2468,11 @@ type Database = {
2460
2468
  user_id?: string | null;
2461
2469
  };
2462
2470
  Update: {
2471
+ context_window_size?: number;
2463
2472
  created_at?: string | null;
2473
+ cumulative_input_tokens?: number;
2474
+ cumulative_output_tokens?: number;
2475
+ deleted_at?: string | null;
2464
2476
  ended_at?: string | null;
2465
2477
  memory_snapshot?: Json;
2466
2478
  metadata?: Json | null;
@@ -3084,6 +3096,18 @@ declare class ResourceRegistry {
3084
3096
  * @throws Error if incoming deployment contains duplicate resourceIds
3085
3097
  */
3086
3098
  registerOrganization(orgName: string, org: OrganizationResources, remote: RemoteOrgConfig): void;
3099
+ /**
3100
+ * Register built-in platform resources (static, local execution)
3101
+ *
3102
+ * Unlike registerOrganization(), these resources:
3103
+ * - Do NOT have remote config (execute in-process, not in worker threads)
3104
+ * - Are NOT removed by unregisterOrganization() (persist across redeployments)
3105
+ * - Use reserved resource IDs that external deployments cannot claim
3106
+ *
3107
+ * @param orgName - Organization name
3108
+ * @param org - Resource definitions with real handlers (not stubs)
3109
+ */
3110
+ registerStaticResources(orgName: string, org: OrganizationResources): void;
3087
3111
  /**
3088
3112
  * Unregister runtime-registered resources for an organization
3089
3113
  *
@@ -3124,6 +3148,14 @@ declare class ResourceRegistry {
3124
3148
  * @returns Remote config or null if org has no remote resources
3125
3149
  */
3126
3150
  getAnyRemoteConfig(orgName: string): RemoteOrgConfig | null;
3151
+ /**
3152
+ * Get statistics about remotely-deployed resources
3153
+ * Used by the health endpoint for platform-wide deployment visibility.
3154
+ */
3155
+ getRemoteStats(): {
3156
+ activeOrgs: number;
3157
+ totalResources: number;
3158
+ };
3127
3159
  /**
3128
3160
  * Get triggers for an organization
3129
3161
  * @param organizationName - Organization name
package/dist/index.js CHANGED
@@ -142,6 +142,12 @@ var DOMAIN_MAP = {
142
142
  [DOMAINS.DIAGNOSTIC]: DIAGNOSTIC_DOMAIN
143
143
  };
144
144
 
145
+ // ../core/src/platform/registry/reserved.ts
146
+ var RESERVED_RESOURCE_IDS = /* @__PURE__ */ new Set(["command-center-assistant"]);
147
+ function isReservedResourceId(resourceId) {
148
+ return RESERVED_RESOURCE_IDS.has(resourceId);
149
+ }
150
+
145
151
  // ../core/src/execution/engine/base/errors.ts
146
152
  var ExecutionError2 = class extends Error {
147
153
  /**
@@ -3295,6 +3301,13 @@ var ResourceRegistry = class {
3295
3301
  }
3296
3302
  seen.add(id);
3297
3303
  }
3304
+ for (const id of incomingIds) {
3305
+ if (isReservedResourceId(id)) {
3306
+ throw new Error(
3307
+ `Resource ID '${id}' is reserved for platform use. External deployments cannot use reserved resource IDs.`
3308
+ );
3309
+ }
3310
+ }
3298
3311
  if (this.isRemote(orgName)) {
3299
3312
  this.unregisterOrganization(orgName);
3300
3313
  }
@@ -3327,6 +3340,46 @@ var ResourceRegistry = class {
3327
3340
  }
3328
3341
  this.serializedCache.set(orgName, serializeOrganization(this.registry[orgName]));
3329
3342
  }
3343
+ /**
3344
+ * Register built-in platform resources (static, local execution)
3345
+ *
3346
+ * Unlike registerOrganization(), these resources:
3347
+ * - Do NOT have remote config (execute in-process, not in worker threads)
3348
+ * - Are NOT removed by unregisterOrganization() (persist across redeployments)
3349
+ * - Use reserved resource IDs that external deployments cannot claim
3350
+ *
3351
+ * @param orgName - Organization name
3352
+ * @param org - Resource definitions with real handlers (not stubs)
3353
+ */
3354
+ registerStaticResources(orgName, org) {
3355
+ const incomingWorkflowIds = (org.workflows ?? []).map((w) => w.config.resourceId);
3356
+ const incomingAgentIds = (org.agents ?? []).map((a) => a.config.resourceId);
3357
+ const incomingIds = [...incomingWorkflowIds, ...incomingAgentIds];
3358
+ const seen = /* @__PURE__ */ new Set();
3359
+ for (const id of incomingIds) {
3360
+ if (seen.has(id)) {
3361
+ throw new Error(`Duplicate resource ID '${id}' in static resources.`);
3362
+ }
3363
+ seen.add(id);
3364
+ }
3365
+ const existingOrg = this.registry[orgName];
3366
+ if (existingOrg) {
3367
+ const existingWorkflowIds = new Set((existingOrg.workflows ?? []).map((w) => w.config.resourceId));
3368
+ const existingAgentIds = new Set((existingOrg.agents ?? []).map((a) => a.config.resourceId));
3369
+ for (const id of incomingIds) {
3370
+ if (existingWorkflowIds.has(id) || existingAgentIds.has(id)) {
3371
+ throw new Error(`Static resource '${id}' conflicts with existing resource in '${orgName}'.`);
3372
+ }
3373
+ }
3374
+ }
3375
+ if (existingOrg) {
3376
+ existingOrg.workflows = [...existingOrg.workflows ?? [], ...org.workflows ?? []];
3377
+ existingOrg.agents = [...existingOrg.agents ?? [], ...org.agents ?? []];
3378
+ } else {
3379
+ this.registry[orgName] = org;
3380
+ }
3381
+ this.serializedCache.set(orgName, serializeOrganization(this.registry[orgName]));
3382
+ }
3330
3383
  /**
3331
3384
  * Unregister runtime-registered resources for an organization
3332
3385
  *
@@ -3410,6 +3463,21 @@ var ResourceRegistry = class {
3410
3463
  }
3411
3464
  return null;
3412
3465
  }
3466
+ /**
3467
+ * Get statistics about remotely-deployed resources
3468
+ * Used by the health endpoint for platform-wide deployment visibility.
3469
+ */
3470
+ getRemoteStats() {
3471
+ const orgs = /* @__PURE__ */ new Set();
3472
+ for (const key of this.remoteResources.keys()) {
3473
+ const orgName = key.split("/")[0];
3474
+ orgs.add(orgName);
3475
+ }
3476
+ return {
3477
+ activeOrgs: orgs.size,
3478
+ totalResources: this.remoteResources.size
3479
+ };
3480
+ }
3413
3481
  // ============================================================================
3414
3482
  // Resource Manifest Accessors
3415
3483
  // ============================================================================
package/dist/templates.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // package.json
2
2
 
3
3
  // src/cli/commands/templates/core/workspace.ts
4
- var TEMPLATE_VERSION = 27;
4
+ var TEMPLATE_VERSION = 28;
5
5
  function configTemplate() {
6
6
  return `import type { ElevasConfig } from '@elevasis/sdk'
7
7
 
@@ -49,6 +49,28 @@ function claudeSettingsTemplate() {
49
49
  }
50
50
  ]
51
51
  }
52
+ ],
53
+ PostToolUse: [
54
+ {
55
+ matcher: "Write|Edit|MultiEdit",
56
+ hooks: [
57
+ {
58
+ type: "command",
59
+ command: "node .claude/hooks/post-edit-validate.mjs"
60
+ }
61
+ ]
62
+ }
63
+ ],
64
+ PostToolUseFailure: [
65
+ {
66
+ matcher: "Bash",
67
+ hooks: [
68
+ {
69
+ type: "command",
70
+ command: "node .claude/hooks/tool-failure-recovery.mjs"
71
+ }
72
+ ]
73
+ }
52
74
  ]
53
75
  }
54
76
  },
@@ -257,16 +279,16 @@ proactivity -- to their assessed levels.
257
279
 
258
280
  | Resource | Location | When to Load |
259
281
  | --- | --- | --- |
260
- | Workspace concepts | \`reference/concepts/index.mdx\` | User asks "what is...?" or needs conceptual grounding |
282
+ | Workspace concepts | \`reference/concepts.mdx\` | User asks "what is...?" or needs conceptual grounding |
261
283
  | SDK patterns and examples | \`reference/resources/patterns.mdx\` | Building or modifying a workflow |
262
284
  | Platform tool catalog | \`reference/platform-tools/index.mdx\` | Connecting to external services |
263
- | CLI reference | \`reference/cli/index.mdx\` | Running execution/platform operations |
264
- | Credential model | \`reference/security/credentials.mdx\` | Setting up integrations or tool access |
265
- | Interaction guidance | \`reference/developer/interaction-guidance.mdx\` | Unsure how to adapt for a skill combination |
285
+ | CLI reference | \`reference/cli.mdx\` | Running execution/platform operations |
286
+ | Credential model | \`reference/platform-tools/index.mdx\` | Setting up integrations or credential security |
287
+ | Interaction guidance | \`reference/framework/interaction-guidance.mdx\` | Unsure how to adapt for a skill combination |
266
288
  | Error history | \`.claude/memory/errors/index.md\` | Debugging errors, checking past fixes |
267
- | Command View model | \`reference/deployment/command-view.mdx\` | Deploying or building resources that invoke other resources |
268
- | Command Center UI reference | \`reference/deployment/command-center-ui.mdx\` | User asks about post-deployment UI or Command Center navigation |
269
- | SDK error reference | \`reference/troubleshooting/common-errors.mdx\` | Unknown error not in workspace memory |
289
+ | Command View model | \`reference/deployment/command-center.mdx\` | Deploying or building resources that invoke other resources |
290
+ | Command Center UI reference | \`reference/deployment/command-center.mdx\` | User asks about post-deployment UI or Command Center navigation |
291
+ | SDK error reference | \`reference/troubleshooting.mdx\` | Unknown error not in workspace memory |
270
292
  | Project map | \`docs/project-map.mdx\` | Session start, project orientation |
271
293
  | Resource inventory | \`docs/resource-map.mdx\` | Finding a specific resource by name or ID |
272
294
  | Project priorities | \`docs/priorities.mdx\` | Deciding what to work on next |
@@ -292,7 +314,7 @@ Use \`pnpm exec elevasis-sdk\` for runtime commands (resolves the locally instal
292
314
  - \`pnpm exec elevasis-sdk execution <resource-id> <execution-id>\` -- inspect execution detail
293
315
 
294
316
  Organization is derived from your API key -- no org prefix needed in the resource ID.
295
- For full CLI reference: \`reference/cli/index.mdx\`
317
+ For full CLI reference: \`reference/cli.mdx\`
296
318
 
297
319
  ## Rules
298
320
 
@@ -307,8 +329,8 @@ SDK patterns (imports, source structure, platform tools) are auto-loaded from
307
329
 
308
330
  When an error occurs:
309
331
  1. Check \`.claude/memory/errors/\` first for past fixes
310
- 2. If new, check \`reference/troubleshooting/common-errors.mdx\`
311
- 3. After resolving, record in \`memory/errors/\` with context and fix
332
+ 2. If new, check \`reference/troubleshooting.mdx\`
333
+ 3. After resolving, record in \`.claude/memory/errors/\` with context and fix
312
334
  4. If an error recurs 3+ times, add a rule to \`.claude/rules/workspace-patterns.md\`${ctx.hasUI ? `
313
335
 
314
336
  ### UI App (\`ui/\`)
@@ -340,7 +362,7 @@ based on what you find.
340
362
  - When growth is observed, note it in the skills.md Growth Log.
341
363
 
342
364
  For detailed per-dimension adaptation rules, read
343
- \`reference/developer/interaction-guidance.mdx\`.
365
+ \`reference/framework/interaction-guidance.mdx\`.
344
366
 
345
367
  ## Commands
346
368
 
@@ -349,7 +371,7 @@ For detailed per-dimension adaptation rules, read
349
371
  | \`/meta\` | Project lifecycle: init, status, fix, deploy, health |
350
372
  | \`/docs\` | Browse, create, and verify permanent documentation |
351
373
  | \`/work\` | Task tracking: create, save, resume, complete |
352
- | \`/tutorial\` | Progressive learning path (7 core lessons + 9 modules) |
374
+ | \`/tutorial\` | Progressive learning path (21 items across 4 sections) |
353
375
 
354
376
  ## Skills
355
377
 
@@ -382,7 +404,7 @@ Do not store in \`.claude/memory/\`:
382
404
 
383
405
  ### Structure
384
406
 
385
- - \`memory/index.md\` is the root -- maps to topic files and subdirectories
407
+ - \`.claude/memory/index.md\` is the root -- maps to topic files and subdirectories
386
408
  - Every subdirectory has its own \`index.md\` mapping to children
387
409
  - Start at the root index and drill down
388
410
  - When a file outgrows a single document, split into a subdirectory
@@ -406,14 +428,14 @@ Read \`.claude/memory/profile/skills.md\` first. The \`automation\` skill level
406
428
  controls which docs you load and which lesson variant you deliver.
407
429
 
408
430
  **automation: none**
409
- - Load from \`reference/concepts/index.mdx\`: Glossary, What is a Workflow,
431
+ - Load from \`reference/concepts.mdx\`: Glossary, What is a Workflow,
410
432
  Platform Tools Overview only. Skip Zod, Execution Model, Design Decisions.
411
- - Load \`reference/deployment/command-center-ui.mdx\` for UI-first teaching.
433
+ - Load \`reference/deployment/command-center.mdx\` for UI-first teaching.
412
434
  - Do NOT load \`reference/resources/patterns.mdx\` or
413
435
  \`reference/platform-tools/adapters.mdx\` during core lessons.
414
436
 
415
437
  **automation: low-code**
416
- - Load all sections of \`reference/concepts/index.mdx\`.
438
+ - Load all sections of \`reference/concepts.mdx\`.
417
439
  - Load \`reference/resources/patterns.mdx\` with Zapier/Make mapping in mind.
418
440
  - Load \`reference/platform-tools/adapters.mdx\` on-demand (when tools are used).
419
441
 
@@ -501,7 +523,7 @@ Each lesson follows this flow:
501
523
 
502
524
  When automation is none:
503
525
  Skip the file tour. Start with what Elevasis does for their business -- use analogies
504
- from \`reference/developer/interaction-guidance.mdx\` (recipe, assembly line, kitchen
526
+ from \`reference/framework/interaction-guidance.mdx\` (recipe, assembly line, kitchen
505
527
  appliance). Explain deployment plainly: "You write the recipe here, then deploy it so
506
528
  it's live." Deploy the starter echo workflow (\`elevasis-sdk check\` + \`elevasis-sdk deploy\`),
507
529
  THEN tour the Command Center so the user sees populated pages, not empty ones. Tour:
@@ -749,14 +771,14 @@ Each module follows this flow:
749
771
  ## Modules
750
772
 
751
773
  **Module: hitl -- Human-in-the-Loop**
752
- Read: \`reference/deployment/command-center-ui.mdx\` (Command Queue section).
774
+ Read: \`reference/deployment/command-center.mdx\` (Command Queue section).
753
775
  Build: Add an approval gate using \`approval.requestApproval()\`. Test full lifecycle:
754
776
  trigger, see pending in Command Queue, approve/reject, observe resume.
755
777
  Key concepts: approval adapter, pending state, Command Queue UI, resume on decision.
756
778
  Verify: Trigger workflow, open Command Queue, approve, confirm completion.
757
779
 
758
780
  **Module: schedules -- Task Scheduling**
759
- Read: \`reference/deployment/command-center-ui.mdx\` (Task Scheduler section).
781
+ Read: \`reference/deployment/command-center.mdx\` (Task Scheduler section).
760
782
  Build: Create all three schedule types (Recurring cron, Relative delay, Absolute
761
783
  datetime). Use \`scheduler\` adapter for in-workflow scheduling.
762
784
  Key concepts: schedule types, cron syntax, scheduler adapter, Task Scheduler UI.
@@ -770,7 +792,7 @@ Verify: Run workflow, check notification in Command Center, confirm email receiv
770
792
 
771
793
  **Module: integrations -- Real-World Integrations**
772
794
  Read: \`reference/platform-tools/index.mdx\`, \`reference/platform-tools/adapters.mdx\`,
773
- \`reference/security/credentials.mdx\`.
795
+ \`reference/platform-tools/index.mdx\`.
774
796
  Build: Pick a real integration adapter based on user's goals (read \`identity.md\`).
775
797
  Set up credential (OAuth via UI, API key via CLI). Build end-to-end integration workflow.
776
798
  Key concepts: adapter pattern, credential scoping, error handling for external calls.
@@ -779,7 +801,7 @@ handling with invalid credential.
779
801
 
780
802
  **Module: error-handling -- Error Handling Mastery**
781
803
  Read: \`reference/resources/patterns.mdx\` (error handling),
782
- \`reference/troubleshooting/common-errors.mdx\`.
804
+ \`reference/troubleshooting.mdx\`.
783
805
  Build: Create a workflow demonstrating all three error types. Add try/catch,
784
806
  \`context.logger\`, and error recovery.
785
807
  Key concepts: ExecutionError, PlatformToolError, ToolingError, recovery patterns.
@@ -795,7 +817,7 @@ Key concepts: context.store, context.logger, domain organization, schema depth.
795
817
  Verify: Run workflow, confirm store values in step output, check logs in Execution Logs.
796
818
 
797
819
  **Module: composition -- Resource Composition**
798
- Read: \`reference/deployment/command-view.mdx\`, \`reference/resources/patterns.mdx\`.
820
+ Read: \`reference/deployment/command-center.mdx\`, \`reference/resources/patterns.mdx\`.
799
821
  Build: Create two workflows where the first triggers the second using
800
822
  \`execution.trigger()\`. Declare the relationship.
801
823
  Key concepts: execution.trigger, relationship declarations, Command View graph edges.
@@ -943,7 +965,7 @@ Last Session: {today's date}
943
965
  \`\`\`
944
966
 
945
967
  Update rules:
946
- - \`Current\`: free-form, e.g. "4: Using Platform Tools" or "M:integrations" or "20: Rules, Memory, and Customization"
968
+ - \`Current\`: free-form, e.g. "7: Using Platform Tools" or "M:integrations" or "20: Rules, Memory, and Customization"
947
969
  - \`Last Session\`: update to today's date on each \`/tutorial\` invocation
948
970
  - Completed Lessons: add a row when any numbered item (1-10, 20-21) finishes
949
971
  - Completed Modules: add a row when any module (items 11-19) finishes
@@ -1039,9 +1061,9 @@ by the \`<!-- initialized: false -->\` flag in CLAUDE.md, or run manually.
1039
1061
  - Create \`.claude/memory/profile/preferences.md\` (verbosity, guidance)
1040
1062
 
1041
1063
  4. **Git check**
1042
- - If \`.git/\` exists: note git is configured in memory/profile/preferences.md
1064
+ - If \`.git/\` exists: note git is configured in .claude/memory/profile/preferences.md
1043
1065
  - If \`.git/\` does not exist: suggest \`git init\` and optionally GitHub
1044
- - If git remote exists: note remote URL in memory/profile/preferences.md
1066
+ - If git remote exists: note remote URL in .claude/memory/profile/preferences.md
1045
1067
 
1046
1068
  5. **Verify project**
1047
1069
  Run \`elevasis-sdk check\` to confirm the starter resource is valid.
@@ -1062,9 +1084,9 @@ by the \`<!-- initialized: false -->\` flag in CLAUDE.md, or run manually.
1062
1084
 
1063
1085
  Display a project health summary:
1064
1086
  1. Template version (from elevasis.config.ts) and installed SDK version (from package.json). Suggest \`elevasis-sdk update\` to check for updates
1065
- 3. Profile summary (from memory/profile/skills.md)
1066
- 4. Quick drift check: count of missing managed files, missing gitignore entries
1067
- 5. Last deployment status (from memory/deployment-state.md if it exists)
1087
+ 2. Profile summary (from .claude/memory/profile/skills.md)
1088
+ 3. Quick drift check: count of missing managed files, missing gitignore entries
1089
+ 4. Last deployment status (from .claude/memory/deployment-state.md if it exists)
1068
1090
 
1069
1091
  ### \`/meta fix\` -- Maintenance and Upgrade
1070
1092
 
@@ -1082,9 +1104,9 @@ Detect and repair all drift. Optionally upgrades the SDK first.
1082
1104
  3. **CLAUDE.md sections:** Add missing sections in correct position
1083
1105
  4. **Memory structure:** Create base structure if missing, then verify index consistency.
1084
1106
  If \`.claude/memory/\` does not exist or is empty:
1085
- - Create \`memory/index.md\` (root index with placeholder entries)
1086
- - Create \`memory/errors/index.md\` (error category summary, empty tables)
1087
- - Create \`memory/errors/deploy.md\`, \`memory/errors/runtime.md\`, \`memory/errors/typescript.md\`
1107
+ - Create \`.claude/memory/index.md\` (root index with placeholder entries)
1108
+ - Create \`.claude/memory/errors/index.md\` (error category summary, empty tables)
1109
+ - Create \`.claude/memory/errors/deploy.md\`, \`.claude/memory/errors/runtime.md\`, \`.claude/memory/errors/typescript.md\`
1088
1110
  If memory exists, verify: every file referenced in an index exists; every file
1089
1111
  without an index entry gets one added; broken references are removed.
1090
1112
  5. **Documentation verification:** For each file in docs/:
@@ -1095,7 +1117,7 @@ Detect and repair all drift. Optionally upgrades the SDK first.
1095
1117
  e. Report discrepancies with suggested fixes
1096
1118
  Note: \`/docs verify\` is available for standalone interactive verification outside this pipeline.
1097
1119
  6. **Settings consistency:** Verify expected fields
1098
- 7. **Rules health:** Scan \`memory/errors/\` -- flag any entry that has recurred
1120
+ 7. **Rules health:** Scan \`.claude/memory/errors/\` -- flag any entry that has recurred
1099
1121
  3+ times and is not yet in \`.claude/rules/workspace-patterns.md\`.
1100
1122
  If \`workspace-patterns.md\` has no rules yet and 5+ resources exist in \`src/\`,
1101
1123
  suggest adding patterns. Surface suggestions only -- do not auto-generate.
@@ -1108,7 +1130,7 @@ Each step reports its result. Steps 1-8 run even if step 0 is skipped.
1108
1130
 
1109
1131
  ### \`/meta deploy\` -- Full Deploy Pipeline
1110
1132
 
1111
- 0. Read \`reference/deployment/command-view.mdx\` -- understand the Command View
1133
+ 0. Read \`reference/deployment/command-center.mdx\` -- understand the Command View
1112
1134
  model, relationship declarations, and what deploy-time validation checks.
1113
1135
  This context is essential for diagnosing validation failures in steps 1-2.
1114
1136
  1. Run \`elevasis-sdk check\` (validation)
@@ -1118,18 +1140,18 @@ Each step reports its result. Steps 1-8 run even if step 0 is skipped.
1118
1140
  5. Run \`elevasis-sdk deploy\`
1119
1141
  6. \`docs/project-map.mdx\` is auto-regenerated by deploy (no manual bump needed)
1120
1142
  7. Verify deployment via platform
1121
- 8. Update \`memory/deployment-state.md\` with count, timestamp, inventory
1143
+ 8. Update \`.claude/memory/deployment-state.md\` with count, timestamp, inventory
1122
1144
  9. If git configured and remote exists: optionally push
1123
1145
 
1124
1146
  Each step reports its result. Pipeline stops on failure with suggested fix.
1125
- If validation fails with relationship errors, re-read \`reference/deployment/command-view.mdx\`
1147
+ If validation fails with relationship errors, re-read \`reference/deployment/command-center.mdx\`
1126
1148
  for the enforcement model and common fixes.
1127
1149
 
1128
1150
  ### \`/meta health\` -- Execution Debugging
1129
1151
 
1130
1152
  Diagnose runtime failures and environment issues:
1131
1153
  - Show recent executions with status (completed/failed)
1132
- - For failed executions: analyze logs, cross-reference with memory/errors/
1154
+ - For failed executions: analyze logs, cross-reference with .claude/memory/errors/
1133
1155
  - Check resource deployment status (deployed, outdated, never deployed)
1134
1156
  - Verify environment: API key valid, credentials accessible, DB connected
1135
1157
 
@@ -1725,6 +1747,199 @@ When all plan steps are marked COMPLETE, suggest \`/work complete\` to finalize
1725
1747
  - Completed tasks move OUT of \`docs/in-progress/\` to \`docs/<relevant-dir>/\`
1726
1748
  `;
1727
1749
  }
1750
+ function claudePostEditValidateHookTemplate() {
1751
+ return `#!/usr/bin/env node
1752
+ // post-edit-validate.mjs
1753
+ // PostToolUse hook \u2014 auto-formats with prettier, type-checks .ts/.tsx files.
1754
+ // Fires after Edit|Write|MultiEdit succeeds.
1755
+
1756
+ import { existsSync } from 'node:fs'
1757
+ import { resolve, normalize, extname, join, dirname } from 'node:path'
1758
+ import { execSync } from 'node:child_process'
1759
+
1760
+ const ROOT = process.env.CLAUDE_PROJECT_DIR ?? process.cwd()
1761
+
1762
+ // Extensions prettier should format
1763
+ const PRETTIER_EXTENSIONS = new Set([
1764
+ '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.json', '.css', '.md', '.mdx'
1765
+ ])
1766
+
1767
+ // Extensions that trigger type-checking
1768
+ const TS_EXTENSIONS = new Set(['.ts', '.tsx'])
1769
+
1770
+ function findNearestTsconfig(startDir) {
1771
+ let dir = startDir
1772
+ const root = normalize(ROOT)
1773
+ while (dir.length >= root.length) {
1774
+ const candidate = join(dir, 'tsconfig.json')
1775
+ if (existsSync(candidate)) return candidate
1776
+ const parent = dirname(dir)
1777
+ if (parent === dir) break
1778
+ dir = parent
1779
+ }
1780
+ return null
1781
+ }
1782
+
1783
+ try {
1784
+ const chunks = []
1785
+ for await (const chunk of process.stdin) chunks.push(chunk)
1786
+ const input = JSON.parse(Buffer.concat(chunks).toString())
1787
+
1788
+ const filePath = input.tool_input?.file_path
1789
+ if (!filePath) process.exit(0)
1790
+
1791
+ const ext = extname(filePath).toLowerCase()
1792
+ const absPath = normalize(resolve(filePath))
1793
+ if (!existsSync(absPath)) process.exit(0)
1794
+
1795
+ const results = []
1796
+
1797
+ // 1. Prettier
1798
+ if (PRETTIER_EXTENSIONS.has(ext)) {
1799
+ try {
1800
+ execSync('pnpm exec prettier --write "' + absPath + '"', {
1801
+ cwd: ROOT,
1802
+ stdio: ['pipe', 'pipe', 'pipe'],
1803
+ timeout: 10_000
1804
+ })
1805
+ } catch (err) {
1806
+ const stderr = err.stderr?.toString().trim() || ''
1807
+ if (stderr && !/ignored/i.test(stderr)) {
1808
+ results.push('Prettier error: ' + stderr.slice(0, 300))
1809
+ }
1810
+ }
1811
+ }
1812
+
1813
+ // 2. Type-check for .ts/.tsx
1814
+ if (TS_EXTENSIONS.has(ext)) {
1815
+ const tsconfig = findNearestTsconfig(dirname(absPath))
1816
+ if (tsconfig) {
1817
+ try {
1818
+ execSync('pnpm exec tsc --noEmit -p "' + tsconfig + '"', {
1819
+ cwd: ROOT,
1820
+ stdio: ['pipe', 'pipe', 'pipe'],
1821
+ timeout: 30_000,
1822
+ env: { ...process.env, NODE_OPTIONS: '--max-old-space-size=4096' }
1823
+ })
1824
+ } catch (err) {
1825
+ if (err.killed) process.exit(0) // Don't block on timeout
1826
+ const stdout = err.stdout?.toString() || ''
1827
+ if (stdout.includes('error TS')) {
1828
+ const errorLines = stdout
1829
+ .split('\\n')
1830
+ .filter(l => l.includes('error TS'))
1831
+ .slice(0, 10)
1832
+ results.push('Type errors after editing ' + filePath + ':\\n' + errorLines.join('\\n'))
1833
+ }
1834
+ }
1835
+ }
1836
+ }
1837
+
1838
+ // Output errors to Claude's context (silence = success)
1839
+ if (results.length > 0) {
1840
+ process.stderr.write(results.join('\\n\\n'))
1841
+ process.exit(2) // Exit 2 = send stderr as feedback to Claude
1842
+ }
1843
+ } catch {}
1844
+
1845
+ process.exit(0)
1846
+ `;
1847
+ }
1848
+ function claudeToolFailureRecoveryHookTemplate() {
1849
+ return `#!/usr/bin/env node
1850
+ // tool-failure-recovery.mjs
1851
+ // PostToolUseFailure hook \u2014 pattern-matches known Bash errors and returns
1852
+ // recovery advice via stderr + exit 2 (feedback to Claude).
1853
+
1854
+ const RECOVERY_TABLE = [
1855
+ {
1856
+ test: r => /JavaScript heap out of memory/i.test(r),
1857
+ advice: 'Out of memory.',
1858
+ fix: 'Run the command with NODE_OPTIONS="--max-old-space-size=4096".',
1859
+ why: 'Large TypeScript projects can exceed Node default heap limit.',
1860
+ },
1861
+ {
1862
+ test: r => /boundary hook/i.test(r) && /block|denied/i.test(r),
1863
+ advice: 'Command blocked by SDK boundary hook.',
1864
+ fix: 'Ask the user to run this command manually.',
1865
+ why: 'The boundary hook blocks gh CLI, destructive git operations, and file writes outside the project.',
1866
+ see: 'CLAUDE.md',
1867
+ },
1868
+ {
1869
+ test: r => /ENOENT/.test(r) && /node_modules/.test(r),
1870
+ advice: 'Missing node_modules dependency.',
1871
+ fix: 'Run: pnpm install',
1872
+ why: 'Dependencies are not installed or were cleared.',
1873
+ },
1874
+ {
1875
+ test: r => /ERR_MODULE_NOT_FOUND/.test(r) && /@elevasis\\/sdk/.test(r),
1876
+ advice: '@elevasis/sdk module not found.',
1877
+ fix: 'Run: pnpm install \u2014 then verify @elevasis/sdk is in package.json dependencies.',
1878
+ why: 'The SDK package is not installed or the version is mismatched.',
1879
+ },
1880
+ {
1881
+ test: r => /ERR_MODULE_NOT_FOUND/.test(r),
1882
+ advice: 'Module not found at import path.',
1883
+ fix: 'Check the import path and verify the package is installed (pnpm install).',
1884
+ why: 'The import path does not match any installed package or local file.',
1885
+ },
1886
+ {
1887
+ test: r => /TS2307/.test(r) || (/cannot find/i.test(r) && /declaration/i.test(r)),
1888
+ advice: 'TypeScript cannot resolve module or declaration file.',
1889
+ fix: 'Check that the package is installed and tsconfig paths are correct.',
1890
+ why: 'Missing dependency or incorrect TypeScript configuration.',
1891
+ },
1892
+ {
1893
+ test: r => /EPERM/.test(r) || /permission denied/i.test(r),
1894
+ advice: 'Permission denied (EPERM).',
1895
+ fix: 'Close the file in any other process (editor, terminal, or dev server) and retry.',
1896
+ why: 'On Windows, files locked by another process cannot be written to.',
1897
+ },
1898
+ {
1899
+ test: r => /lockfile/i.test(r) && /conflict|outdated|ERR_PNPM/i.test(r),
1900
+ advice: 'pnpm lockfile conflict or outdated.',
1901
+ fix: 'Run: pnpm install to regenerate the lockfile.',
1902
+ why: 'The lockfile is out of sync with package.json changes.',
1903
+ },
1904
+ {
1905
+ test: r => /elevasis-sdk check/.test(r) || /elevasis-sdk deploy/.test(r),
1906
+ advice: 'elevasis-sdk CLI command failed.',
1907
+ fix: 'Check the error output above. Common causes: missing .env ELEVASIS_API_KEY, invalid resource schemas, or network issues.',
1908
+ why: 'The SDK CLI validates resources and communicates with the platform API.',
1909
+ },
1910
+ {
1911
+ test: r => /EADDRINUSE/.test(r),
1912
+ advice: 'Port already in use.',
1913
+ fix: 'Find and kill the process using the port, or use a different port.',
1914
+ why: 'A previous dev server or process is still holding the port.',
1915
+ },
1916
+ ]
1917
+
1918
+ function formatRecovery(entry) {
1919
+ let msg = 'FAILED: ' + entry.advice + '\\nFIX: ' + entry.fix
1920
+ if (entry.why) msg += '\\nWHY: ' + entry.why
1921
+ if (entry.see) msg += '\\nSEE: ' + entry.see
1922
+ return msg
1923
+ }
1924
+
1925
+ try {
1926
+ const chunks = []
1927
+ for await (const chunk of process.stdin) chunks.push(chunk)
1928
+ const input = JSON.parse(Buffer.concat(chunks).toString())
1929
+
1930
+ const response = input.tool_response ?? ''
1931
+
1932
+ for (const entry of RECOVERY_TABLE) {
1933
+ if (entry.test(response)) {
1934
+ process.stderr.write(formatRecovery(entry))
1935
+ process.exit(2)
1936
+ }
1937
+ }
1938
+ } catch {}
1939
+
1940
+ process.exit(0)
1941
+ `;
1942
+ }
1728
1943
 
1729
1944
  // src/cli/commands/templates/core/resources.ts
1730
1945
  function starterWorkflowTemplate() {
@@ -1882,6 +2097,8 @@ function getManagedTemplates(ctx = {}) {
1882
2097
  ".claude/settings.json": claudeSettingsTemplate,
1883
2098
  ".claude/scripts/statusline-command.js": claudeStatuslineScriptTemplate,
1884
2099
  ".claude/hooks/enforce-sdk-boundary.mjs": claudeSdkBoundaryHookTemplate,
2100
+ ".claude/hooks/post-edit-validate.mjs": claudePostEditValidateHookTemplate,
2101
+ ".claude/hooks/tool-failure-recovery.mjs": claudeToolFailureRecoveryHookTemplate,
1885
2102
  ".claude/commands/tutorial.md": claudeTutorialCommandTemplate,
1886
2103
  ".claude/commands/meta.md": claudeMetaCommandTemplate,
1887
2104
  ".claude/commands/work.md": claudeWorkCommandTemplate,
@@ -3596,13 +3596,9 @@ function validateActionSequence(actions) {
3596
3596
  throw new Error("Multiple complete actions not allowed in single iteration");
3597
3597
  }
3598
3598
  if (completeActions.length === 1) {
3599
- const hasIncompatibleActions = actions.some(
3600
- (a) => a.type === "tool-call" || a.type === "navigate-knowledge"
3601
- );
3602
- if (hasIncompatibleActions) {
3603
- throw new Error(
3604
- "Complete action cannot mix with tool-call or navigate-knowledge actions"
3605
- );
3599
+ const hasNavigateKnowledge = actions.some((a) => a.type === "navigate-knowledge");
3600
+ if (hasNavigateKnowledge) {
3601
+ throw new Error("Complete action cannot mix with navigate-knowledge actions");
3606
3602
  }
3607
3603
  }
3608
3604
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/sdk",
3
- "version": "0.5.13",
3
+ "version": "0.5.15",
4
4
  "description": "SDK for building Elevasis organization resources",
5
5
  "type": "module",
6
6
  "bin": {