@elevasis/sdk 1.7.0 → 1.8.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.
Files changed (39) hide show
  1. package/dist/cli.cjs +525 -4562
  2. package/dist/index.d.ts +72 -16
  3. package/package.json +2 -2
  4. package/reference/claude-config/hooks/post-edit-validate.mjs +0 -11
  5. package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +188 -0
  6. package/reference/claude-config/logs/pre-edit-vibe-gate.log +17 -0
  7. package/reference/claude-config/logs/scaffold-registry-reminder.log +34 -0
  8. package/reference/claude-config/rules/active-change-index.md +80 -0
  9. package/reference/claude-config/rules/agent-start-here.md +254 -0
  10. package/reference/claude-config/rules/deployment.md +0 -1
  11. package/reference/claude-config/rules/observability.md +2 -2
  12. package/reference/claude-config/rules/operations.md +64 -0
  13. package/reference/claude-config/rules/organization-model.md +44 -0
  14. package/reference/claude-config/rules/organization-os.md +2 -4
  15. package/reference/claude-config/rules/task-tracking.md +4 -4
  16. package/reference/claude-config/rules/ui.md +202 -0
  17. package/reference/claude-config/rules/vibe.md +0 -8
  18. package/reference/claude-config/settings.json +4 -11
  19. package/reference/claude-config/skills/configure/SKILL.md +0 -2
  20. package/reference/claude-config/skills/configure/operations/features.md +10 -11
  21. package/reference/claude-config/skills/deploy/SKILL.md +4 -14
  22. package/reference/claude-config/skills/dsp/SKILL.md +2 -2
  23. package/reference/claude-config/skills/elevasis/SKILL.md +24 -28
  24. package/reference/claude-config/skills/explore/SKILL.md +5 -5
  25. package/reference/claude-config/skills/project/SKILL.md +33 -1
  26. package/reference/claude-config/skills/save/SKILL.md +8 -22
  27. package/reference/claude-config/skills/setup/SKILL.md +32 -16
  28. package/reference/claude-config/skills/status/SKILL.md +2 -3
  29. package/reference/claude-config/skills/submit-request/SKILL.md +1 -1
  30. package/reference/deployment/command-center.mdx +0 -17
  31. package/reference/framework/project-structure.mdx +1 -5
  32. package/reference/packages/ui/src/hooks/README.md +1 -2
  33. package/reference/scaffold/operations/propagation-pipeline.md +10 -11
  34. package/reference/scaffold/operations/scaffold-maintenance.md +1 -4
  35. package/reference/scaffold/recipes/add-a-resource.md +3 -12
  36. package/reference/scaffold/reference/contracts.md +1 -1
  37. package/reference/claude-config/hooks/__tests__/pre-edit-vibe-gate.test.mjs +0 -169
  38. package/reference/claude-config/hooks/pre-edit-vibe-gate.mjs +0 -128
  39. package/reference/claude-config/rules/docs.md +0 -26
@@ -30,11 +30,11 @@ Layer 3: Sync Verification (pnpm sync:verify)
30
30
 
31
31
  `pnpm scaffold:sync` is the meta-script that regenerates all derived documentation and validates the output. It chains three sub-scripts:
32
32
 
33
- | Script | Input | Output |
34
- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
35
- | `generate-scaffold-contracts.js` | `packages/core/src/organization-model/types.ts`, `packages/ui/src/features/registry/types.ts`, `packages/core/src/platform/registry/types.ts` | `packages/core/src/reference/_generated/contracts.md` |
36
- | `generate-scaffold-feature-registry.js` | `packages/ui/src/features/*/manifest.ts`, `packages/core/src/organization-model/domains/features.ts` | `packages/ui/src/scaffold/_generated/feature-registry.md` |
37
- | `generate-reference-artifacts.js` | SDK manifest, navigation sources | `packages/sdk/reference/_reference-manifest.json`, `_navigation.md`, `external/_template/docs/platform-navigation-map.md` |
33
+ | Script | Input | Output |
34
+ | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
35
+ | `generate-scaffold-contracts.js` | `packages/core/src/organization-model/types.ts`, `packages/ui/src/features/registry/types.ts`, `packages/core/src/platform/registry/types.ts` | `packages/core/src/reference/_generated/contracts.md` |
36
+ | `generate-scaffold-feature-registry.js` | `packages/ui/src/features/*/manifest.ts`, `packages/core/src/organization-model/domains/features.ts` | `packages/ui/src/scaffold/_generated/feature-registry.md` |
37
+ | `generate-reference-artifacts.js` | SDK manifest, navigation sources | `packages/sdk/reference/_reference-manifest.json`, `_navigation.md` |
38
38
 
39
39
  After generation, `validate-reference-artifacts.js` checks that the outputs are consistent. Exit 1 if drifted.
40
40
 
@@ -55,11 +55,11 @@ Drift is healed at the moment it would otherwise leak downstream. This is cheape
55
55
 
56
56
  `/external sync` propagates the `external/_template` to downstream projects. It uses a three-tier model:
57
57
 
58
- | Tier | Policy | Examples |
59
- | ------------------------------ | ----------------------------------------- | ------------------------------------------------------------------- |
58
+ | Tier | Policy | Examples |
59
+ | ------------------------------ | ----------------------------------------- | --------------------------------------------------------------------- |
60
60
  | **Tier 1 (Infrastructure)** | Always replaced from template | Configs, shared runtime surfaces, `lib/`, `test-utils/`, entry points |
61
- | **Tier 2 (Standard Features)** | Synced unless project has customized them | Standard UI features, common patterns |
62
- | **Tier 3 (Project-Specific)** | Never touched | `nav-items.ts`, `operations/src/`, `docs/`, `CLAUDE.md` |
61
+ | **Tier 2 (Standard Features)** | Synced unless project has customized them | Standard UI features, common patterns |
62
+ | **Tier 3 (Project-Specific)** | Never touched | `nav-items.ts`, `operations/src/`, `docs/`, `CLAUDE.md` |
63
63
 
64
64
  The sync skill doc (`.claude/skills/external/SKILL.md`) defines the full tier model and phase sequence.
65
65
 
@@ -78,8 +78,7 @@ The sync skill doc (`.claude/skills/external/SKILL.md`) defines the full tier mo
78
78
  | `org-os` | Organization model exists, exports canonical symbols, imports from `@elevasis/core/organization-model`, calls `defineOrganizationModel` + `resolveOrganizationModel`, app-config references org model, `__root.tsx` uses `ElevasisFeaturesProvider` + `canonicalOrganizationModel`, `main.tsx` uses `ElevasisUIProvider`, all 3 CSS subpath imports present |
79
79
  | `placeholders` | No unresolved `__PROJECT_SLUG__`, `__PROJECT_NAME__`, `__PROJECT_DESCRIPTION__` in key config files |
80
80
  | `scripts` | `ui` and `operations` `package.json` have required npm scripts |
81
- | `generated-docs` | `docs/index.md` and `docs/resources.md` are current with `pnpm exec elevasis-sdk generate-docs` and `pnpm exec elevasis-sdk generate-resources`; `pnpm exec elevasis-sdk validate-docs` passes |
82
- | `lib` | `ui/src/lib/`, `lib/`, `test-utils/` exist with minimum file counts |
81
+ | `lib` | `ui/src/lib/`, `lib/`, `test-utils/` exist with minimum file counts |
83
82
  | `tier3` | `nav-items.ts` has project-specific customization (not overwritten by template) |
84
83
  | `conflicts` | No merge conflict markers in source files |
85
84
  | `git` | Working tree is clean |
@@ -71,7 +71,6 @@ Generated by `scripts/monorepo/generate-reference-artifacts.js`:
71
71
 
72
72
  - `packages/sdk/reference/_reference-manifest.json` -- machine-readable catalog of all reference entries
73
73
  - `packages/sdk/reference/_navigation.md` -- navigation table
74
- - `external/_template/docs/platform-navigation-map.md` -- cross-package reference map for external projects
75
74
 
76
75
  ### Running Generators
77
76
 
@@ -120,6 +119,4 @@ The output lands in `packages/sdk/reference/` which is included in the npm packa
120
119
 
121
120
  ## Freshness Validation
122
121
 
123
- External projects validate generated docs with `pnpm check:autogenerated-docs`, which now calls `pnpm exec elevasis-sdk validate-docs`. The legacy `scripts/validate-autogenerated-docs.mjs` file may still exist as a temporary compatibility shim in the template, but the SDK CLI is the canonical path.
124
-
125
- At the monorepo level, `pnpm scaffold:sync` followed by `pnpm sync:verify` confirms that all artifacts are current and all downstream projects are consistent.
122
+ At the monorepo level, `pnpm scaffold:sync` followed by `pnpm sync:verify` confirms that all artifacts are current and all downstream projects are consistent. The SDK no longer ships doc validation because external projects no longer carry a `docs/` tree.
@@ -109,7 +109,7 @@ const org: DeploymentSpec = {
109
109
  }
110
110
  ```
111
111
 
112
- Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). The generated `docs/resources.md` topology map will reflect these in the Topology Relationships, Triggers, and Human Checkpoints sections after regeneration.
112
+ Full relationship and checkpoint types are defined in `@elevasis/sdk` (`DeploymentSpec`). Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly.
113
113
 
114
114
  ---
115
115
 
@@ -133,18 +133,9 @@ See `OrganizationModelResourceMapping` in [contracts.md](../reference/contracts.
133
133
 
134
134
  ---
135
135
 
136
- ## 5. Regenerate the topology map
136
+ ## 5. Verify resource inventory
137
137
 
138
- ```bash
139
- pnpm exec elevasis-sdk generate-resources
140
- ```
141
-
142
- Open `docs/resources.md` and confirm:
143
-
144
- - Section 1 (Workflows table) lists the new resource with correct `resourceId`, `version`, and `status`.
145
- - Section 2 (Topology Relationships) shows any declared `relationships` edges.
146
- - Sections 3-6 (Triggers, Integrations, Human Checkpoints, External Resources) show any relevant declarations.
147
- - Section 7 (Schema Signatures) includes the new resource's input/output field list.
138
+ Resources are discovered live via `pnpm elevasis-sdk project:list` or by globbing `operations/resources/**` directly. Confirm the new resource appears with the correct `resourceId`, `version`, and `status`.
148
139
 
149
140
  ---
150
141
 
@@ -1,4 +1,4 @@
1
- <!-- Auto-generated on 2026-04-20T23:27:16.482Z by scripts/monorepo/generate-scaffold-contracts.js -->
1
+ <!-- Auto-generated on 2026-04-21T08:23:05.375Z by scripts/monorepo/generate-scaffold-contracts.js -->
2
2
  ---
3
3
  title: Reference Contracts
4
4
  description: Auto-generated TypeScript contracts for SDK consumers. Do not edit manually.
@@ -1,169 +0,0 @@
1
- #!/usr/bin/env node
2
- // pre-edit-vibe-gate.test.mjs
3
- // Tests for the pre-edit-vibe-gate hook.
4
- // Run with: node --test .claude/hooks/__tests__/pre-edit-vibe-gate.test.mjs
5
- //
6
- // Tests the exported `isProtectedPath` helper directly (pure logic, no stdin/stdout
7
- // mocking needed). Integration cases simulate the full hook by spawning it as a
8
- // child process.
9
-
10
- import { describe, it } from 'node:test'
11
- import assert from 'node:assert/strict'
12
- import { spawnSync } from 'node:child_process'
13
- import { resolve, dirname } from 'node:path'
14
- import { fileURLToPath, pathToFileURL } from 'node:url'
15
-
16
- const __dirname = dirname(fileURLToPath(import.meta.url))
17
- const HOOK_PATH = resolve(__dirname, '..', 'pre-edit-vibe-gate.mjs')
18
-
19
- // Import the exported helper for unit-level tests.
20
- // Using a dynamic import so the module's top-level await (stdin read) doesn't
21
- // execute — the hook guards that behind the stdin loop which only runs when
22
- // there is actual input; unit tests call the exported function directly.
23
- // On Windows, absolute paths must be converted to file:// URLs for ESM imports.
24
- const { isProtectedPath } = await import(pathToFileURL(HOOK_PATH).href)
25
-
26
- // Template root = 3 levels up from __tests__/
27
- const TEMPLATE_ROOT = resolve(__dirname, '..', '..', '..')
28
-
29
- // ---------------------------------------------------------------------------
30
- // Helper: run the hook as a subprocess with a synthetic PreToolUse event.
31
- // filePath may be relative (to template root) or already absolute.
32
- // ---------------------------------------------------------------------------
33
- function runHook(toolName, filePath, env = {}) {
34
- // Claude always sends absolute paths to hooks. Resolve relative paths
35
- // against the template root so toRelative() inside the hook works correctly.
36
- const absFilePath =
37
- filePath.startsWith('/') || /^[A-Za-z]:/.test(filePath) ? filePath : resolve(TEMPLATE_ROOT, filePath)
38
-
39
- const event = JSON.stringify({
40
- tool_name: toolName,
41
- tool_input: { file_path: absFilePath }
42
- })
43
-
44
- return spawnSync(process.execPath, [HOOK_PATH], {
45
- input: event,
46
- encoding: 'utf-8',
47
- env: {
48
- ...process.env,
49
- // Override AFTER spreading so this always wins over any ambient value
50
- CLAUDE_PROJECT_DIR: TEMPLATE_ROOT,
51
- ...env
52
- },
53
- timeout: 5000
54
- })
55
- }
56
-
57
- // ---------------------------------------------------------------------------
58
- // Unit tests — isProtectedPath (pure function, no process spawning)
59
- // ---------------------------------------------------------------------------
60
-
61
- describe('isProtectedPath — exact protected files', () => {
62
- it('blocks organization-model.ts', () => {
63
- assert.equal(isProtectedPath('foundations/config/organization-model.ts'), true)
64
- })
65
-
66
- it('blocks organization-model.examples.ts', () => {
67
- assert.equal(isProtectedPath('foundations/config/organization-model.examples.ts'), true)
68
- })
69
-
70
- it('blocks organization-model.override.ts', () => {
71
- assert.equal(isProtectedPath('foundations/config/organization-model.override.ts'), true)
72
- })
73
- })
74
-
75
- describe('isProtectedPath — extensions glob', () => {
76
- it('blocks a .ts file directly under extensions/', () => {
77
- assert.equal(isProtectedPath('foundations/config/extensions/deal-ecom.ts'), true)
78
- })
79
-
80
- it('blocks a .ts file in a subdirectory under extensions/', () => {
81
- assert.equal(isProtectedPath('foundations/config/extensions/crm/deal-ecom.ts'), true)
82
- })
83
-
84
- it('blocks the discriminated-union index.ts under extensions/', () => {
85
- assert.equal(isProtectedPath('foundations/config/extensions/index.ts'), true)
86
- })
87
-
88
- it('does NOT block a non-.ts file under extensions/', () => {
89
- assert.equal(isProtectedPath('foundations/config/extensions/README.md'), false)
90
- })
91
- })
92
-
93
- describe('isProtectedPath — unrelated paths always pass', () => {
94
- it('allows ui/ files', () => {
95
- assert.equal(isProtectedPath('ui/src/routes/__root.tsx'), false)
96
- })
97
-
98
- it('allows operations/ files', () => {
99
- assert.equal(isProtectedPath('operations/src/index.ts'), false)
100
- })
101
-
102
- it('allows foundations/types (not config)', () => {
103
- assert.equal(isProtectedPath('foundations/types/entities.ts'), false)
104
- })
105
-
106
- it('does NOT block a partial-match path that is not under foundations/config', () => {
107
- // "organization-model.ts" without the full prefix should not be blocked
108
- assert.equal(isProtectedPath('src/organization-model.ts'), false)
109
- })
110
- })
111
-
112
- describe('isProtectedPath — partial path / edge cases', () => {
113
- it('does not block foundations/config/ itself (no .ts suffix)', () => {
114
- // The directory path should not be blocked
115
- assert.equal(isProtectedPath('foundations/config/'), false)
116
- })
117
-
118
- it('strips leading ./ before matching', () => {
119
- assert.equal(isProtectedPath('./foundations/config/organization-model.ts'), true)
120
- })
121
- })
122
-
123
- // ---------------------------------------------------------------------------
124
- // Integration tests — spawn the hook with synthetic events
125
- // ---------------------------------------------------------------------------
126
-
127
- describe('hook subprocess — blocked without VIBE_APPROVED', () => {
128
- it('exits 2 for Write to organization-model.ts', () => {
129
- const result = runHook('Write', 'foundations/config/organization-model.ts')
130
- assert.equal(result.status, 2, `expected exit 2, got ${result.status}`)
131
- assert.ok(result.stderr.includes('BLOCKED'), 'expected BLOCKED in stderr')
132
- })
133
-
134
- it('exits 2 for Edit to extensions/deal-ecom.ts', () => {
135
- const result = runHook('Edit', 'foundations/config/extensions/deal-ecom.ts')
136
- assert.equal(result.status, 2)
137
- assert.ok(result.stderr.includes('BLOCKED'))
138
- })
139
-
140
- it('exits 2 for MultiEdit to organization-model.override.ts', () => {
141
- const result = runHook('MultiEdit', 'foundations/config/organization-model.override.ts')
142
- assert.equal(result.status, 2)
143
- assert.ok(result.stderr.includes('BLOCKED'))
144
- })
145
- })
146
-
147
- describe('hook subprocess — passes with VIBE_APPROVED=1', () => {
148
- it('exits 0 for Write to organization-model.ts when VIBE_APPROVED=1', () => {
149
- const result = runHook('Write', 'foundations/config/organization-model.ts', { VIBE_APPROVED: '1' })
150
- assert.equal(result.status, 0, `expected exit 0, got ${result.status}`)
151
- })
152
-
153
- it('exits 0 for Edit to extensions/deal-ecom.ts when VIBE_APPROVED=1', () => {
154
- const result = runHook('Edit', 'foundations/config/extensions/deal-ecom.ts', { VIBE_APPROVED: '1' })
155
- assert.equal(result.status, 0)
156
- })
157
- })
158
-
159
- describe('hook subprocess — unrelated path always passes', () => {
160
- it('exits 0 for Write to ui/src/routes/__root.tsx without VIBE_APPROVED', () => {
161
- const result = runHook('Write', 'ui/src/routes/__root.tsx')
162
- assert.equal(result.status, 0)
163
- })
164
-
165
- it('exits 0 for Edit to operations/src/index.ts without VIBE_APPROVED', () => {
166
- const result = runHook('Edit', 'operations/src/index.ts')
167
- assert.equal(result.status, 0)
168
- })
169
- })
@@ -1,128 +0,0 @@
1
- #!/usr/bin/env node
2
- // pre-edit-vibe-gate.mjs
3
- // PreToolUse backstop — blocks raw writes to protected foundations/config paths
4
- // unless the VIBE_APPROVED=1 trust marker is present.
5
- //
6
- // Protected paths (relative to project root):
7
- // foundations/config/organization-model.ts
8
- // foundations/config/organization-model.examples.ts
9
- // foundations/config/organization-model.override.ts
10
- // foundations/config/extensions/**/*.ts
11
- //
12
- // To allow a write: set VIBE_APPROVED=1 in the environment before invoking the
13
- // agent, or run /configure which sets the marker automatically after user
14
- // confirmation.
15
-
16
- import { appendFileSync, mkdirSync } from 'node:fs'
17
- import { normalize, resolve, relative, sep } from 'node:path'
18
- import { fileURLToPath } from 'node:url'
19
-
20
- const ROOT = normalize(process.env.CLAUDE_PROJECT_DIR ?? process.cwd())
21
- const LOG_DIR = ROOT + sep + '.claude' + sep + 'logs'
22
- const LOG_FILE = LOG_DIR + sep + 'pre-edit-vibe-gate.log'
23
-
24
- function log(msg) {
25
- try {
26
- mkdirSync(LOG_DIR, { recursive: true })
27
- appendFileSync(LOG_FILE, `[${new Date().toISOString()}] ${msg}\n`)
28
- } catch {
29
- // Never crash on log failure
30
- }
31
- }
32
-
33
- /**
34
- * Normalise an incoming file path (may be absolute or project-relative) to a
35
- * forward-slash relative path from ROOT for consistent matching.
36
- */
37
- function toRelative(filePath) {
38
- const abs = normalize(resolve(filePath))
39
- // relative() returns OS-separator paths — normalise to forward slashes
40
- return relative(ROOT, abs).replace(/\\/g, '/')
41
- }
42
-
43
- /**
44
- * Returns true if `rel` (forward-slash relative path from root) matches one of
45
- * the protected path patterns. No external deps — uses simple string checks.
46
- *
47
- * Protected patterns:
48
- * foundations/config/organization-model.ts (exact)
49
- * foundations/config/organization-model.examples.ts (exact)
50
- * foundations/config/organization-model.override.ts (exact)
51
- * foundations/config/extensions/**\/*.ts (glob — any .ts under extensions/)
52
- */
53
- export function isProtectedPath(rel) {
54
- // Normalise away any leading ./
55
- const r = rel.replace(/^\.\//, '')
56
-
57
- // Exact protected files
58
- const EXACT = [
59
- 'foundations/config/organization-model.ts',
60
- 'foundations/config/organization-model.examples.ts',
61
- 'foundations/config/organization-model.override.ts'
62
- ]
63
- if (EXACT.includes(r)) return true
64
-
65
- // Glob: foundations/config/extensions/**/*.ts
66
- // Must start with the prefix, end with .ts, and have at least one path segment
67
- // after the extensions/ directory.
68
- const EXT_PREFIX = 'foundations/config/extensions/'
69
- if (r.startsWith(EXT_PREFIX) && r.endsWith('.ts')) {
70
- // Ensure there is at least one filename after the prefix (not just the dir itself)
71
- const remainder = r.slice(EXT_PREFIX.length)
72
- if (remainder.length > 3) return true // at least "x.ts"
73
- }
74
-
75
- return false
76
- }
77
-
78
- const BLOCK_MESSAGE =
79
- 'BLOCKED: This file is protected by the vibe gate.\n' +
80
- 'WHY: Direct edits to foundations/config/organization-model.ts and\n' +
81
- ' foundations/config/extensions/*.ts bypass the ambient vibe ceremony\n' +
82
- ' (confirm + /configure write + pnpm check-types).\n' +
83
- 'FIX: Run /configure to codify changes with proper ceremony (sets VIBE_APPROVED=1\n' +
84
- ' automatically), or set VIBE_APPROVED=1 explicitly if you are a power user\n' +
85
- ' who has already completed the ceremony manually.'
86
-
87
- // Only run the stdin-reading main loop when this file is the entry point,
88
- // not when it is imported as a module (e.g., by tests).
89
- const isMain =
90
- process.argv[1] != null && normalize(fileURLToPath(import.meta.url)) === normalize(resolve(process.argv[1]))
91
-
92
- if (isMain) {
93
- try {
94
- const chunks = []
95
- for await (const chunk of process.stdin) chunks.push(chunk)
96
- const input = JSON.parse(Buffer.concat(chunks).toString())
97
-
98
- const toolName = input.tool_name ?? ''
99
- const filePath = input.tool_input?.file_path ?? ''
100
-
101
- // Only gate Write, Edit, MultiEdit
102
- if (!['Write', 'Edit', 'MultiEdit'].includes(toolName)) {
103
- log(`SKIP tool=${toolName} (not a write tool)`)
104
- process.exit(0)
105
- }
106
-
107
- if (!filePath) {
108
- log(`SKIP tool=${toolName} no file_path in input`)
109
- process.exit(0)
110
- }
111
-
112
- const rel = toRelative(filePath)
113
- const protected_ = isProtectedPath(rel)
114
- const approved = process.env.VIBE_APPROVED === '1'
115
- const decision = protected_ && !approved ? 'BLOCK' : 'ALLOW'
116
-
117
- log(`tool=${toolName} path=${rel} protected=${protected_} VIBE_APPROVED=${approved} decision=${decision}`)
118
-
119
- if (decision === 'BLOCK') {
120
- process.stderr.write(BLOCK_MESSAGE)
121
- process.exit(2)
122
- }
123
- } catch (err) {
124
- log(`ERROR: ${err?.message ?? String(err)}`)
125
- }
126
-
127
- process.exit(0)
128
- }
@@ -1,26 +0,0 @@
1
- ---
2
- description: Documentation conventions -- structure, frontmatter, /save integration, auto-generated files
3
- paths:
4
- - docs/**
5
- ---
6
-
7
- # Documentation
8
-
9
- ## Safety Invariants
10
-
11
- - `docs/index.md` and `docs/resources.md` are auto-generated by the SDK CLI -- never edit manually
12
- - Regenerate: `pnpm exec elevasis-sdk generate-docs` / `pnpm exec elevasis-sdk generate-resources`
13
- - Validate: `pnpm exec elevasis-sdk validate-docs` (or `pnpm check:autogenerated-docs`)
14
- - Every `.md` file in `docs/` MUST have `title` and `description` frontmatter -- docs without it are skipped by the index generator
15
- - In-progress docs additionally require `status: planned | in-progress | complete`
16
-
17
- ## Structure
18
-
19
- - All docs are Markdown (`.md`), not MDX -- external projects don't use Fumadocs
20
- - UI features → `docs/ui/`, platform features → `docs/operations/`, knowledge → `docs/knowledge/`
21
- - New subdirectories under `docs/` are automatically discovered by the index generator
22
-
23
- ## Detailed Reference
24
-
25
- - `docs/index.md` -- auto-generated navigation hub (full doc map)
26
- - `docs/agent-start-here.md` -- canonical agent entrypoint and task-routing guidance