studiograph 1.2.0-beta.9 → 1.2.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.
- package/README.md +13 -18
- package/dist/agent/orchestrator.d.ts +56 -0
- package/dist/agent/orchestrator.js +167 -22
- package/dist/agent/orchestrator.js.map +1 -1
- package/dist/agent/prompts/system.md +51 -63
- package/dist/agent/skill-loader.js +8 -0
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/skills/entity-schema.md +4 -19
- package/dist/agent/skills/gather-context.md +1 -1
- package/dist/agent/tools/graph-tools.d.ts +41 -1
- package/dist/agent/tools/graph-tools.js +133 -57
- package/dist/agent/tools/graph-tools.js.map +1 -1
- package/dist/agent/tools/ops-tools.js +82 -0
- package/dist/agent/tools/ops-tools.js.map +1 -1
- package/dist/agent/tools/permission-tools.d.ts +90 -0
- package/dist/agent/tools/permission-tools.js +207 -0
- package/dist/agent/tools/permission-tools.js.map +1 -0
- package/dist/agent/tools/sync-tools.js +2 -2
- package/dist/agent/tools/sync-tools.js.map +1 -1
- package/dist/auth/github.d.ts +1 -1
- package/dist/auth/github.js +21 -13
- package/dist/auth/github.js.map +1 -1
- package/dist/cli/commands/access.d.ts +11 -0
- package/dist/cli/commands/access.js +156 -0
- package/dist/cli/commands/access.js.map +1 -0
- package/dist/cli/commands/app.js +25 -2
- package/dist/cli/commands/app.js.map +1 -1
- package/dist/cli/commands/clear.d.ts +5 -0
- package/dist/cli/commands/clear.js +36 -0
- package/dist/cli/commands/clear.js.map +1 -0
- package/dist/cli/commands/clone.js +3 -3
- package/dist/cli/commands/clone.js.map +1 -1
- package/dist/cli/commands/collection.d.ts +10 -0
- package/dist/cli/commands/collection.js +187 -0
- package/dist/cli/commands/collection.js.map +1 -0
- package/dist/cli/commands/commit.js +2 -1
- package/dist/cli/commands/commit.js.map +1 -1
- package/dist/cli/commands/config.d.ts +100 -0
- package/dist/cli/commands/config.js +1 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/deploy.js +10 -1
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/index.js.map +1 -1
- package/dist/cli/commands/init.js +32 -40
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/join.d.ts +0 -6
- package/dist/cli/commands/join.js +26 -111
- package/dist/cli/commands/join.js.map +1 -1
- package/dist/cli/commands/lint.js +1 -2
- package/dist/cli/commands/lint.js.map +1 -1
- package/dist/cli/commands/mcp.js +6 -5
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/org.d.ts +10 -0
- package/dist/cli/commands/org.js +132 -0
- package/dist/cli/commands/org.js.map +1 -0
- package/dist/cli/commands/orphans.js +1 -2
- package/dist/cli/commands/orphans.js.map +1 -1
- package/dist/cli/commands/provision.js +3 -3
- package/dist/cli/commands/provision.js.map +1 -1
- package/dist/cli/commands/resolve.d.ts +8 -0
- package/dist/cli/commands/resolve.js +85 -0
- package/dist/cli/commands/resolve.js.map +1 -0
- package/dist/cli/commands/serve.js +55 -25
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/commands/start.js +22 -205
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/sync.js +53 -8
- package/dist/cli/commands/sync.js.map +1 -1
- package/dist/cli/commands/team.d.ts +12 -0
- package/dist/cli/commands/team.js +185 -0
- package/dist/cli/commands/team.js.map +1 -0
- package/dist/cli/index.js +41 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/scaffolding.d.ts +5 -3
- package/dist/cli/scaffolding.js +191 -97
- package/dist/cli/scaffolding.js.map +1 -1
- package/dist/cli/setup-wizard.js +20 -10
- package/dist/cli/setup-wizard.js.map +1 -1
- package/dist/cli/sync-review-interactive.js +1 -1
- package/dist/cli/sync-review-interactive.js.map +1 -1
- package/dist/core/graph.d.ts +5 -10
- package/dist/core/graph.js +84 -85
- package/dist/core/graph.js.map +1 -1
- package/dist/core/migration-runner.d.ts +42 -0
- package/dist/core/migration-runner.js +232 -0
- package/dist/core/migration-runner.js.map +1 -0
- package/dist/core/migration-types.d.ts +101 -0
- package/dist/core/migration-types.js +21 -0
- package/dist/core/migration-types.js.map +1 -0
- package/dist/core/migrations/20260219-formalize-memory-location.d.ts +2 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js +35 -0
- package/dist/core/migrations/20260219-formalize-memory-location.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.d.ts +12 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js +65 -0
- package/dist/core/migrations/20260220-add-workspace-metadata.js.map +1 -0
- package/dist/core/migrations/20260220-add-workspace-readme.d.ts +11 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js +82 -0
- package/dist/core/migrations/20260220-add-workspace-readme.js.map +1 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.d.ts +9 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js +64 -0
- package/dist/core/migrations/20260220-migrate-yaml-to-json.js.map +1 -0
- package/dist/core/migrations/index.d.ts +11 -0
- package/dist/core/migrations/index.js +23 -0
- package/dist/core/migrations/index.js.map +1 -0
- package/dist/core/types.d.ts +19 -34
- package/dist/core/types.js +3 -21
- package/dist/core/types.js.map +1 -1
- package/dist/core/user-config.d.ts +27 -0
- package/dist/core/user-config.js +51 -0
- package/dist/core/user-config.js.map +1 -1
- package/dist/core/validation.d.ts +978 -2182
- package/dist/core/validation.js +242 -397
- package/dist/core/validation.js.map +1 -1
- package/dist/core/workspace-manager.d.ts +32 -31
- package/dist/core/workspace-manager.js +171 -186
- package/dist/core/workspace-manager.js.map +1 -1
- package/dist/core/workspace.d.ts +0 -5
- package/dist/core/workspace.js +33 -101
- package/dist/core/workspace.js.map +1 -1
- package/dist/lib/lib/utils.d.ts +2 -0
- package/dist/lib/lib/utils.js +6 -0
- package/dist/lib/lib/utils.js.map +1 -0
- package/dist/mcp/tools.js +13 -13
- package/dist/mcp/tools.js.map +1 -1
- package/dist/server/chrome/chrome.css +562 -0
- package/dist/server/chrome/chrome.js +540 -0
- package/dist/server/index.js +163 -10
- package/dist/server/index.js.map +1 -1
- package/dist/server/plugin-loader.d.ts +7 -0
- package/dist/server/plugin-loader.js +9 -1
- package/dist/server/plugin-loader.js.map +1 -1
- package/dist/server/routes/chat.d.ts +3 -2
- package/dist/server/routes/chat.js +67 -16
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/git-api.d.ts +9 -0
- package/dist/server/routes/git-api.js +82 -0
- package/dist/server/routes/git-api.js.map +1 -0
- package/dist/server/routes/graph-api.d.ts +2 -2
- package/dist/server/routes/graph-api.js +267 -3
- package/dist/server/routes/graph-api.js.map +1 -1
- package/dist/server/routes/permissions-api.d.ts +9 -0
- package/dist/server/routes/permissions-api.js +176 -0
- package/dist/server/routes/permissions-api.js.map +1 -0
- package/dist/server/routes/workspace-api.d.ts +9 -0
- package/dist/server/routes/workspace-api.js +283 -0
- package/dist/server/routes/workspace-api.js.map +1 -0
- package/dist/services/assets/base.d.ts +2 -2
- package/dist/services/assets/base.js +4 -4
- package/dist/services/assets/base.js.map +1 -1
- package/dist/services/assets/index.d.ts +6 -6
- package/dist/services/assets/index.js +12 -12
- package/dist/services/assets/index.js.map +1 -1
- package/dist/services/git.d.ts +35 -0
- package/dist/services/git.js +93 -0
- package/dist/services/git.js.map +1 -1
- package/dist/services/github-provisioner.js +1 -2
- package/dist/services/github-provisioner.js.map +1 -1
- package/dist/services/github-service.d.ts +99 -0
- package/dist/services/github-service.js +310 -0
- package/dist/services/github-service.js.map +1 -0
- package/dist/services/markdown.js +4 -9
- package/dist/services/markdown.js.map +1 -1
- package/dist/services/memory-service.d.ts +4 -0
- package/dist/services/memory-service.js +13 -1
- package/dist/services/memory-service.js.map +1 -1
- package/dist/services/sync/commit.d.ts +2 -0
- package/dist/services/sync/commit.js +21 -6
- package/dist/services/sync/commit.js.map +1 -1
- package/dist/services/sync/graphrag-indexer.js +2 -2
- package/dist/services/sync/graphrag-indexer.js.map +1 -1
- package/dist/utils/git.d.ts +5 -0
- package/dist/utils/git.js +10 -0
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/merge-resolver.d.ts +33 -8
- package/dist/utils/merge-resolver.js +157 -55
- package/dist/utils/merge-resolver.js.map +1 -1
- package/dist/utils/preflight.d.ts +1 -1
- package/dist/utils/preflight.js +1 -1
- package/dist/web/_app/env.js +1 -0
- package/dist/web/_app/immutable/assets/0.CDbX4Cwz.css +1 -0
- package/dist/web/_app/immutable/assets/2.DRHi7ABa.css +1 -0
- package/dist/web/_app/immutable/assets/3.BJy7pVXi.css +1 -0
- package/dist/web/_app/immutable/assets/4.Ad16uh9o.css +1 -0
- package/dist/web/_app/immutable/assets/5.BhKgiXd2.css +1 -0
- package/dist/web/_app/immutable/assets/6.CeHKR5ZY.css +1 -0
- package/dist/web/_app/immutable/assets/AppShell.CJtUfb0N.css +1 -0
- package/dist/web/_app/immutable/assets/ChatPanel.RFD5GGYI.css +1 -0
- package/dist/web/_app/immutable/assets/editor.CPAf2SRV.css +1 -0
- package/dist/web/_app/immutable/chunks/3_5VIr68.js +1 -0
- package/dist/web/_app/immutable/chunks/4QY4j-jX.js +1 -0
- package/dist/web/_app/immutable/chunks/BB_5th5W.js +3383 -0
- package/dist/web/_app/immutable/chunks/BButMJ6M.js +1 -0
- package/dist/web/_app/immutable/chunks/BiubvAUI.js +2 -0
- package/dist/web/_app/immutable/chunks/CAXuTUkp.js +1 -0
- package/dist/web/_app/immutable/chunks/CQENNNNl.js +6 -0
- package/dist/web/_app/immutable/chunks/CUzqHQY_.js +1 -0
- package/dist/web/_app/immutable/chunks/CV8ganSj.js +23 -0
- package/dist/web/_app/immutable/chunks/CYrVHOHA.js +1 -0
- package/dist/web/_app/immutable/chunks/CqkleIqs.js +1 -0
- package/dist/web/_app/immutable/chunks/DKyztuK9.js +1 -0
- package/dist/web/_app/immutable/chunks/DdNsM6oV.js +64 -0
- package/dist/web/_app/immutable/chunks/Dh_H7Owr.js +18 -0
- package/dist/web/_app/immutable/chunks/DnlgZ_Tk.js +5 -0
- package/dist/web/_app/immutable/chunks/DtVH--hH.js +6 -0
- package/dist/web/_app/immutable/chunks/F20aIBpJ.js +1 -0
- package/dist/web/_app/immutable/chunks/PPVm8Dsz.js +1 -0
- package/dist/web/_app/immutable/chunks/WSUKABI_.js +1 -0
- package/dist/web/_app/immutable/chunks/YFT1281h.js +2 -0
- package/dist/web/_app/immutable/chunks/aosHekRC.js +1 -0
- package/dist/web/_app/immutable/chunks/fwnBoL5x.js +1 -0
- package/dist/web/_app/immutable/chunks/hHxe9oXh.js +1 -0
- package/dist/web/_app/immutable/entry/app.BFVUP2fV.js +2 -0
- package/dist/web/_app/immutable/entry/start.BqsXHYP6.js +1 -0
- package/dist/web/_app/immutable/nodes/0.DQ5KdeNU.js +1 -0
- package/dist/web/_app/immutable/nodes/1.DwnzyOvm.js +1 -0
- package/dist/web/_app/immutable/nodes/2.FZxrWJeh.js +1 -0
- package/dist/web/_app/immutable/nodes/3.CQVWlbKr.js +1 -0
- package/dist/web/_app/immutable/nodes/4.CEh40Z_h.js +16 -0
- package/dist/web/_app/immutable/nodes/5.D_QsCLEf.js +4 -0
- package/dist/web/_app/immutable/nodes/6.CndEQ0o5.js +2 -0
- package/dist/web/_app/version.json +1 -0
- package/dist/web/index.html +43 -0
- package/package.json +21 -3
- package/dist/agent/skills/bundled/enrich-entities.md +0 -124
- package/dist/agent/skills/bundled/gather-context.md +0 -46
package/dist/core/validation.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Entity validation schemas for Studiograph
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* 17 built-in entity types organized into three categories:
|
|
5
|
+
* - Identity (4): person, organization, role, practice-area
|
|
6
|
+
* - Universal (10): project, meeting, decision, task, document, dataset, reference, note, deliverable, publication
|
|
7
|
+
* - Knowledge (3): process, standard, case-study
|
|
8
|
+
*
|
|
9
|
+
* App plugins register additional types at runtime via SchemaRegistry.
|
|
10
|
+
* Teams can define custom types via schema_extensions in workspace config.
|
|
6
11
|
*/
|
|
7
12
|
import { z } from 'zod';
|
|
8
13
|
/**
|
|
@@ -17,305 +22,255 @@ export const EntityBaseSchema = z.object({
|
|
|
17
22
|
updated_at: z.string().datetime('Invalid datetime format'),
|
|
18
23
|
created_by: z.string().min(1, 'Created by is required'),
|
|
19
24
|
updated_by: z.string().min(1, 'Updated by is required'),
|
|
20
|
-
visibility: z.enum(['public', 'team', 'admin', 'restricted'])
|
|
21
|
-
.default('team')
|
|
22
|
-
.describe('Access level for this entity'),
|
|
23
|
-
restricted_to: z.array(z.string())
|
|
24
|
-
.optional()
|
|
25
|
-
.describe('User IDs with access (if visibility=restricted)'),
|
|
26
|
-
sensitive_fields: z.array(z.string())
|
|
27
|
-
.optional()
|
|
28
|
-
.describe('Fields that contain sensitive data'),
|
|
29
25
|
tags: z.array(z.string())
|
|
30
26
|
.optional()
|
|
31
27
|
.describe('Tags for categorization'),
|
|
32
28
|
}).passthrough(); // Allow custom fields beyond the base schema
|
|
29
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
30
|
+
// IDENTITY ENTITIES — people, organizations, roles, practice areas
|
|
31
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
32
|
+
/**
|
|
33
|
+
* Person — team members, client contacts, any individual
|
|
34
|
+
*/
|
|
35
|
+
export const PersonSchema = EntityBaseSchema.extend({
|
|
36
|
+
entity_type: z.literal('person'),
|
|
37
|
+
name: z.string().min(1, 'Person name is required'),
|
|
38
|
+
role: z.string().optional().describe('Role or title'),
|
|
39
|
+
status: z.enum(['current', 'former', 'contractor', 'client', 'partner'])
|
|
40
|
+
.optional()
|
|
41
|
+
.describe('Relationship status'),
|
|
42
|
+
email: z.string().optional().describe('Email address'),
|
|
43
|
+
location: z.string().optional().describe('Location'),
|
|
44
|
+
organization: z.string().optional().describe('Organization wikilink'),
|
|
45
|
+
bio: z.string().optional().describe('Biography (markdown)'),
|
|
46
|
+
projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
47
|
+
reports_to: z.string().optional().describe('Manager or role wikilink'),
|
|
48
|
+
department: z.string().optional().describe('Department'),
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Organization — clients, vendors, partners, prospects, industry bodies
|
|
52
|
+
* Replaces the former separate client and vendor types.
|
|
53
|
+
*/
|
|
54
|
+
export const OrganizationSchema = EntityBaseSchema.extend({
|
|
55
|
+
entity_type: z.literal('organization'),
|
|
56
|
+
name: z.string().min(1, 'Organization name is required'),
|
|
57
|
+
type: z.enum(['client', 'vendor', 'partner', 'prospect', 'industry-body', 'other'])
|
|
58
|
+
.optional()
|
|
59
|
+
.describe('Relationship type'),
|
|
60
|
+
status: z.enum(['active', 'inactive', 'prospect', 'former'])
|
|
61
|
+
.default('active')
|
|
62
|
+
.describe('Organization status'),
|
|
63
|
+
industry: z.string().optional().describe('Industry sector'),
|
|
64
|
+
website: z.string().url().optional().describe('Website URL'),
|
|
65
|
+
location: z.string().optional().describe('Primary location'),
|
|
66
|
+
size: z.enum(['small', 'medium', 'large', 'enterprise'])
|
|
67
|
+
.optional()
|
|
68
|
+
.describe('Organization size'),
|
|
69
|
+
contacts: z.array(z.string()).optional().describe('Contact person wikilinks'),
|
|
70
|
+
projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
71
|
+
relationship_start: z.string().optional().describe('When the relationship started'),
|
|
72
|
+
});
|
|
33
73
|
/**
|
|
34
|
-
*
|
|
35
|
-
* Used in project-specific repositories (one per client/project)
|
|
74
|
+
* Role — role definitions from the firm's leveling framework
|
|
36
75
|
*/
|
|
76
|
+
export const RoleSchema = EntityBaseSchema.extend({
|
|
77
|
+
entity_type: z.literal('role'),
|
|
78
|
+
title: z.string().min(1, 'Role title is required'),
|
|
79
|
+
department: z.string().optional().describe('Department'),
|
|
80
|
+
level: z.number().optional().describe('Level 1–5 from leveling framework'),
|
|
81
|
+
type: z.enum(['staff', 'contractor', 'intern'])
|
|
82
|
+
.optional()
|
|
83
|
+
.describe('Employment type'),
|
|
84
|
+
status: z.enum(['active', 'archived'])
|
|
85
|
+
.default('active')
|
|
86
|
+
.describe('Role status'),
|
|
87
|
+
location: z.string().optional().describe('Location'),
|
|
88
|
+
reports_to: z.string().optional().describe('Parent role or person wikilink'),
|
|
89
|
+
});
|
|
37
90
|
/**
|
|
38
|
-
*
|
|
91
|
+
* Practice Area — firm capabilities and disciplines
|
|
92
|
+
*/
|
|
93
|
+
export const PracticeAreaSchema = EntityBaseSchema.extend({
|
|
94
|
+
entity_type: z.literal('practice-area'),
|
|
95
|
+
name: z.string().min(1, 'Practice area name is required'),
|
|
96
|
+
description: z.string().optional().describe('Overview of the discipline'),
|
|
97
|
+
capabilities: z.array(z.string()).optional().describe('Specific service offerings'),
|
|
98
|
+
related_case_studies: z.array(z.string()).optional().describe('Case study wikilinks'),
|
|
99
|
+
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
100
|
+
});
|
|
101
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
102
|
+
// UNIVERSAL ENTITIES — available in any repo
|
|
103
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
104
|
+
/**
|
|
105
|
+
* Project — a client engagement or internal initiative
|
|
106
|
+
* Subtypes via `type` field: client-project, internal-initiative, event, research
|
|
39
107
|
*/
|
|
40
108
|
export const ProjectSchema = EntityBaseSchema.extend({
|
|
41
109
|
entity_type: z.literal('project'),
|
|
42
110
|
name: z.string().min(1, 'Project name is required'),
|
|
43
|
-
|
|
111
|
+
type: z.string().optional().describe('Project subtype (e.g., client-project, internal-initiative, event, research)'),
|
|
112
|
+
client: z.string().optional().describe('Client organization wikilink'),
|
|
44
113
|
website_url: z.string().url().optional().describe('Project website URL'),
|
|
45
|
-
start_date: z.string().optional().describe('Project start date
|
|
114
|
+
start_date: z.string().optional().describe('Project start date'),
|
|
46
115
|
end_date: z.string().optional().describe('Project end date'),
|
|
47
|
-
target_completion: z.string().optional().describe('Target completion date'),
|
|
48
|
-
year_released: z.number().optional().describe('Year the project was released'),
|
|
49
116
|
status: z.enum(['planning', 'scoping', 'active', 'on-hold', 'completed', 'archived'])
|
|
50
117
|
.optional()
|
|
51
118
|
.describe('Current project status'),
|
|
52
119
|
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
53
|
-
related_areas: z.array(z.string()).optional().describe('Practice
|
|
120
|
+
related_areas: z.array(z.string()).optional().describe('Practice area wikilinks'),
|
|
54
121
|
team: z.array(z.string()).optional().describe('Team member wikilinks'),
|
|
55
|
-
deliverables: z.array(z.string()).optional().describe('
|
|
122
|
+
deliverables: z.array(z.string()).optional().describe('Deliverable wikilinks'),
|
|
56
123
|
deal: z.string().optional().describe('Originating deal wikilink'),
|
|
57
124
|
});
|
|
58
125
|
/**
|
|
59
|
-
* Meeting
|
|
126
|
+
* Meeting — any scheduled gathering
|
|
127
|
+
* Subtypes via `type` field: internal, client, workshop, conference, industry-event
|
|
60
128
|
*/
|
|
61
129
|
export const MeetingSchema = EntityBaseSchema.extend({
|
|
62
130
|
entity_type: z.literal('meeting'),
|
|
63
131
|
name: z.string().min(1, 'Meeting name/subject is required'),
|
|
64
|
-
|
|
65
|
-
|
|
132
|
+
type: z.string().optional().describe('Meeting subtype (e.g., internal, client, workshop, conference, industry-event)'),
|
|
133
|
+
date: z.string().optional().describe('Meeting date'),
|
|
134
|
+
attendees: z.array(z.string()).optional().describe('Attendee wikilinks'),
|
|
66
135
|
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
67
136
|
related_organizations: z.array(z.string()).optional().describe('Related organization wikilinks'),
|
|
68
137
|
related_areas: z.array(z.string()).optional().describe('Practice area wikilinks'),
|
|
69
138
|
agenda: z.string().optional().describe('Meeting agenda (markdown)'),
|
|
70
|
-
notes: z.string().optional().describe('Meeting notes (markdown)'),
|
|
71
139
|
action_items: z.array(z.string()).optional().describe('Action items from the meeting'),
|
|
72
140
|
summary: z.string().optional().describe('Meeting summary'),
|
|
73
141
|
});
|
|
74
142
|
/**
|
|
75
|
-
* Decision
|
|
76
|
-
* Format: DEC-YYYY-NNN
|
|
143
|
+
* Decision — structured decision records (ADR-style)
|
|
77
144
|
*/
|
|
78
145
|
export const DecisionSchema = EntityBaseSchema.extend({
|
|
79
146
|
entity_type: z.literal('decision'),
|
|
80
|
-
id: z.string()
|
|
81
|
-
.regex(/^DEC-\d{4}-\d{3}$/, 'Decision ID must be in format DEC-YYYY-NNN')
|
|
82
|
-
.describe('Unique decision identifier'),
|
|
83
147
|
title: z.string().min(1, 'Decision title is required'),
|
|
84
|
-
date: z.string().describe('Decision date
|
|
148
|
+
date: z.string().optional().describe('Decision date'),
|
|
85
149
|
status: z.enum(['proposed', 'accepted', 'rejected', 'deprecated', 'superseded'])
|
|
86
150
|
.default('proposed')
|
|
87
|
-
.describe('Current status
|
|
88
|
-
decision_makers: z.array(z.string())
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
supersedes: z.string()
|
|
98
|
-
.optional()
|
|
99
|
-
.describe('Decision this one replaces (wikilink)'),
|
|
100
|
-
superseded_by: z.string()
|
|
101
|
-
.optional()
|
|
102
|
-
.describe('Decision that replaces this one (wikilink)'),
|
|
103
|
-
context: z.string()
|
|
104
|
-
.optional()
|
|
105
|
-
.describe('Background and why this decision was needed'),
|
|
106
|
-
alternatives: z.string()
|
|
107
|
-
.optional()
|
|
108
|
-
.describe('Alternatives considered (markdown)'),
|
|
109
|
-
decision: z.string()
|
|
110
|
-
.optional()
|
|
111
|
-
.describe('The actual decision made'),
|
|
112
|
-
rationale: z.string()
|
|
113
|
-
.optional()
|
|
114
|
-
.describe('Why this decision was chosen'),
|
|
115
|
-
consequences: z.string()
|
|
116
|
-
.optional()
|
|
117
|
-
.describe('Positive/negative outcomes and risks'),
|
|
118
|
-
enables: z.array(z.string())
|
|
119
|
-
.optional()
|
|
120
|
-
.describe('Decisions this one enables'),
|
|
151
|
+
.describe('Current status'),
|
|
152
|
+
decision_makers: z.array(z.string()).optional().describe('People who made the decision'),
|
|
153
|
+
stakeholders: z.array(z.string()).optional().describe('People affected'),
|
|
154
|
+
context: z.string().optional().describe('Background and why this decision was needed'),
|
|
155
|
+
alternatives: z.string().optional().describe('Alternatives considered (markdown)'),
|
|
156
|
+
decision: z.string().optional().describe('The actual decision made'),
|
|
157
|
+
rationale: z.string().optional().describe('Why this decision was chosen'),
|
|
158
|
+
consequences: z.string().optional().describe('Outcomes and risks'),
|
|
159
|
+
supersedes: z.string().optional().describe('Decision this one replaces (wikilink)'),
|
|
160
|
+
superseded_by: z.string().optional().describe('Decision that replaces this one (wikilink)'),
|
|
121
161
|
});
|
|
122
162
|
/**
|
|
123
|
-
* Task
|
|
163
|
+
* Task — lightweight action items and to-dos
|
|
124
164
|
*/
|
|
125
165
|
export const TaskSchema = EntityBaseSchema.extend({
|
|
126
166
|
entity_type: z.literal('task'),
|
|
127
167
|
name: z.string().min(1, 'Task name is required'),
|
|
128
|
-
assignee: z.string()
|
|
129
|
-
|
|
130
|
-
.describe('Person assigned to this task (wikilink)'),
|
|
131
|
-
due_date: z.string()
|
|
132
|
-
.optional()
|
|
133
|
-
.describe('Due date (ISO 8601 or human-readable)'),
|
|
168
|
+
assignee: z.string().optional().describe('Person assigned (wikilink)'),
|
|
169
|
+
due_date: z.string().optional().describe('Due date'),
|
|
134
170
|
status: z.enum(['open', 'in-progress', 'done', 'cancelled'])
|
|
135
171
|
.default('open')
|
|
136
|
-
.describe('
|
|
172
|
+
.describe('Task status'),
|
|
137
173
|
priority: z.enum(['low', 'medium', 'high', 'urgent'])
|
|
138
174
|
.optional()
|
|
139
|
-
.describe('
|
|
140
|
-
project: z.string()
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
.optional()
|
|
145
|
-
.describe('Related deliverable (wikilink)'),
|
|
146
|
-
related_meeting: z.string()
|
|
147
|
-
.optional()
|
|
148
|
-
.describe('Meeting this task came from (wikilink)'),
|
|
149
|
-
description: z.string()
|
|
150
|
-
.optional()
|
|
151
|
-
.describe('Detailed description of the task'),
|
|
175
|
+
.describe('Priority level'),
|
|
176
|
+
project: z.string().optional().describe('Related project (wikilink)'),
|
|
177
|
+
deliverable: z.string().optional().describe('Related deliverable (wikilink)'),
|
|
178
|
+
related_meeting: z.string().optional().describe('Meeting this task came from (wikilink)'),
|
|
179
|
+
description: z.string().optional().describe('Detailed description'),
|
|
152
180
|
});
|
|
153
181
|
/**
|
|
154
|
-
*
|
|
182
|
+
* Document — any authored document
|
|
183
|
+
* Subtypes via `type` field: proposal, contract, brief, memo, financial-plan, template, report
|
|
184
|
+
* Absorbs the former separate proposal, contract, brief, financial-plan, and template types.
|
|
155
185
|
*/
|
|
156
|
-
export const
|
|
157
|
-
entity_type: z.literal('
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
186
|
+
export const DocumentSchema = EntityBaseSchema.extend({
|
|
187
|
+
entity_type: z.literal('document'),
|
|
188
|
+
name: z.string().min(1, 'Document name is required'),
|
|
189
|
+
type: z.string().optional().describe('Document subtype (e.g., proposal, contract, brief, memo, financial-plan, template, report)'),
|
|
190
|
+
client: z.string().optional().describe('Client organization wikilink'),
|
|
191
|
+
project: z.string().optional().describe('Related project wikilink'),
|
|
192
|
+
date: z.string().optional().describe('Document date'),
|
|
193
|
+
version: z.string().optional().describe('Version (e.g., v1, v2)'),
|
|
194
|
+
status: z.enum(['draft', 'sent', 'accepted', 'rejected', 'negotiating', 'signed', 'completed', 'terminated'])
|
|
195
|
+
.default('draft')
|
|
196
|
+
.describe('Document status'),
|
|
197
|
+
description: z.string().optional().describe('Description or summary'),
|
|
198
|
+
});
|
|
199
|
+
/**
|
|
200
|
+
* Dataset — structured tabular data with typed columns and CSV body
|
|
201
|
+
*/
|
|
202
|
+
export const ColumnDefinitionSchema = z.object({
|
|
203
|
+
name: z.string().min(1),
|
|
204
|
+
type: z.enum(['string', 'number', 'boolean', 'date']),
|
|
205
|
+
required: z.boolean().optional(),
|
|
206
|
+
description: z.string().optional(),
|
|
207
|
+
});
|
|
208
|
+
export const DatasetSchema = EntityBaseSchema.extend({
|
|
209
|
+
entity_type: z.literal('dataset'),
|
|
210
|
+
name: z.string().min(1, 'Dataset name is required'),
|
|
211
|
+
schema: z.array(ColumnDefinitionSchema).min(1, 'At least one column required'),
|
|
212
|
+
});
|
|
213
|
+
/**
|
|
214
|
+
* Reference — external resources and inspiration
|
|
215
|
+
* Subtypes via `type` field: article, video, tool, technique, framework, website
|
|
216
|
+
* Absorbs the former separate technique type.
|
|
217
|
+
*/
|
|
218
|
+
export const ReferenceSchema = EntityBaseSchema.extend({
|
|
219
|
+
entity_type: z.literal('reference'),
|
|
220
|
+
name: z.string().min(1, 'Reference name is required'),
|
|
221
|
+
type: z.string().optional().describe('Reference subtype (e.g., article, video, tool, technique, framework, website)'),
|
|
222
|
+
date: z.string().optional().describe('Publication date'),
|
|
223
|
+
source: z.string().optional().describe('Source/author'),
|
|
224
|
+
link: z.string().optional().describe('URL'),
|
|
171
225
|
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
226
|
+
related_areas: z.array(z.string()).optional().describe('Related practice areas'),
|
|
227
|
+
description: z.string().optional().describe('Description'),
|
|
172
228
|
});
|
|
173
229
|
/**
|
|
174
|
-
*
|
|
230
|
+
* Note — freeform thinking, research, scratch, daily notes
|
|
231
|
+
* Lightweight entity with minimal schema. Participates in the graph like any other entity.
|
|
175
232
|
*/
|
|
176
|
-
export const
|
|
177
|
-
entity_type: z.literal('
|
|
178
|
-
|
|
179
|
-
type: z.string()
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
project: z.string().optional().describe('Related project wikilink'),
|
|
183
|
-
deliverable: z.string().optional().describe('Parent deliverable wikilink'),
|
|
184
|
-
date_created: z.string().optional().describe('Creation date'),
|
|
185
|
-
description: z.string().optional().describe('Artifact description'),
|
|
186
|
-
url: z.string().optional().describe('URL or file path'),
|
|
187
|
-
version: z.string().optional().describe('Version number'),
|
|
233
|
+
export const NoteSchema = EntityBaseSchema.extend({
|
|
234
|
+
entity_type: z.literal('note'),
|
|
235
|
+
title: z.string().optional().describe('Note title'),
|
|
236
|
+
type: z.string().optional().describe('Note subtype (e.g., research, scratch, daily, brainstorm, draft)'),
|
|
237
|
+
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
238
|
+
related_organizations: z.array(z.string()).optional().describe('Related organization wikilinks'),
|
|
188
239
|
});
|
|
189
240
|
/**
|
|
190
|
-
* Deliverable
|
|
191
|
-
*
|
|
192
|
-
* Operates at a higher level than individual artifacts: a deliverable is the
|
|
193
|
-
* "big ticket item" committed to in a proposal or contract (e.g. "Brand
|
|
194
|
-
* Identity System"), while artifacts are the individual produced items within
|
|
195
|
-
* it (logo SVG, style guide PDF, brand guidelines deck).
|
|
196
|
-
*
|
|
197
|
-
* Bridges the commercial side (proposal, contract) to the execution side
|
|
198
|
-
* (artifact): proposal.deliverables[] → deliverable → artifact[]
|
|
241
|
+
* Deliverable — a scoped contractual output promised to a client
|
|
242
|
+
* Bridges the commercial side (proposal, contract) to execution (artifacts, tasks).
|
|
199
243
|
*/
|
|
200
244
|
export const DeliverableSchema = EntityBaseSchema.extend({
|
|
201
245
|
entity_type: z.literal('deliverable'),
|
|
202
246
|
name: z.string().min(1, 'Deliverable name is required'),
|
|
203
247
|
project: z.string().optional().describe('Related project wikilink'),
|
|
204
|
-
proposal: z.string().optional().describe('Originating proposal wikilink'),
|
|
205
|
-
contract: z.string().optional().describe('Formalizing contract wikilink'),
|
|
206
|
-
artifacts: z.array(z.string()).optional().describe('Component artifact wikilinks'),
|
|
207
248
|
status: z.enum(['planned', 'in-progress', 'delivered', 'accepted', 'rejected'])
|
|
208
249
|
.default('planned')
|
|
209
250
|
.describe('Delivery status'),
|
|
210
|
-
due_date: z.string().optional().describe('Due date
|
|
251
|
+
due_date: z.string().optional().describe('Due date'),
|
|
211
252
|
delivered_date: z.string().optional().describe('Actual delivery date'),
|
|
212
253
|
description: z.string().optional().describe('What this deliverable comprises'),
|
|
213
254
|
});
|
|
214
255
|
/**
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*/
|
|
218
|
-
/**
|
|
219
|
-
* Proposal entity - client proposals and SOWs
|
|
256
|
+
* Publication — authored content published externally
|
|
257
|
+
* Subtypes via `type` field: article, social-post, case-study-writeup, talk, podcast, award-submission
|
|
220
258
|
*/
|
|
221
|
-
export const
|
|
222
|
-
entity_type: z.literal('
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
version: z.string().optional().describe('Version (e.g., v1, v2)'),
|
|
228
|
-
status: z.enum(['draft', 'sent', 'accepted', 'rejected', 'negotiating'])
|
|
259
|
+
export const PublicationSchema = EntityBaseSchema.extend({
|
|
260
|
+
entity_type: z.literal('publication'),
|
|
261
|
+
title: z.string().min(1, 'Publication title is required'),
|
|
262
|
+
type: z.string().optional().describe('Publication subtype (e.g., article, social-post, talk, podcast, award-submission)'),
|
|
263
|
+
platform: z.string().optional().describe('Platform (e.g., linkedin, medium, behance, conference)'),
|
|
264
|
+
status: z.enum(['draft', 'review', 'scheduled', 'published'])
|
|
229
265
|
.default('draft')
|
|
230
|
-
.describe('
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
fees: z.string().optional().describe('Fee structure'),
|
|
236
|
-
payment_terms: z.string().optional().describe('Payment terms and schedule'),
|
|
237
|
-
});
|
|
238
|
-
/**
|
|
239
|
-
* Contract entity - SOWs, MSAs, NDAs
|
|
240
|
-
*/
|
|
241
|
-
export const ContractSchema = EntityBaseSchema.extend({
|
|
242
|
-
entity_type: z.literal('contract'),
|
|
243
|
-
name: z.string().min(1, 'Contract name is required'),
|
|
244
|
-
type: z.enum(['sow', 'msa', 'nda', 'other'])
|
|
245
|
-
.optional()
|
|
246
|
-
.describe('Contract type'),
|
|
247
|
-
client: z.string().optional().describe('Client name or wikilink'),
|
|
248
|
-
project: z.string().optional().describe('Related project wikilink'),
|
|
249
|
-
date_signed: z.string().optional().describe('Signature date'),
|
|
250
|
-
start_date: z.string().optional().describe('Contract start date'),
|
|
251
|
-
end_date: z.string().optional().describe('Contract end date'),
|
|
252
|
-
status: z.enum(['draft', 'pending', 'signed', 'completed', 'terminated'])
|
|
253
|
-
.default('draft')
|
|
254
|
-
.describe('Contract status'),
|
|
255
|
-
value: z.string().optional().describe('Contract value'),
|
|
256
|
-
payment_terms: z.string().optional().describe('Payment terms'),
|
|
257
|
-
});
|
|
258
|
-
/**
|
|
259
|
-
* Person entity - team members, clients, contacts
|
|
260
|
-
*/
|
|
261
|
-
export const PersonSchema = EntityBaseSchema.extend({
|
|
262
|
-
entity_type: z.literal('person'),
|
|
263
|
-
name: z.string().min(1, 'Person name is required'),
|
|
264
|
-
role: z.string().optional().describe('Role or title'),
|
|
265
|
-
status: z.enum(['current', 'former', 'contractor', 'client', 'partner'])
|
|
266
|
-
.optional()
|
|
267
|
-
.describe('Relationship status'),
|
|
268
|
-
email: z.string().optional().describe('Email address'),
|
|
269
|
-
location: z.string().optional().describe('Location'),
|
|
270
|
-
organization: z.string().optional().describe('Organization wikilink'),
|
|
271
|
-
years_experience: z.number().optional().describe('Years of experience'),
|
|
272
|
-
bio: z.string().optional().describe('Biography (markdown)'),
|
|
273
|
-
projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
274
|
-
reports_to: z.string().optional().describe('Manager or role wikilink'),
|
|
275
|
-
department: z.string().optional().describe('Department (e.g. Creative Technology, Design)'),
|
|
276
|
-
});
|
|
277
|
-
/**
|
|
278
|
-
* Client entity - client organizations and companies
|
|
279
|
-
*/
|
|
280
|
-
export const ClientSchema = EntityBaseSchema.extend({
|
|
281
|
-
entity_type: z.literal('client'),
|
|
282
|
-
name: z.string().min(1, 'Client name is required'),
|
|
283
|
-
type: z.enum(['corporate', 'nonprofit', 'government', 'startup', 'agency', 'other'])
|
|
284
|
-
.optional()
|
|
285
|
-
.describe('Organization type'),
|
|
286
|
-
status: z.enum(['active', 'inactive', 'prospect', 'former'])
|
|
287
|
-
.default('active')
|
|
288
|
-
.describe('Client status'),
|
|
289
|
-
industry: z.string().optional().describe('Industry sector'),
|
|
290
|
-
website: z.string().url().optional().describe('Website URL'),
|
|
291
|
-
location: z.string().optional().describe('Primary location'),
|
|
292
|
-
size: z.enum(['small', 'medium', 'large', 'enterprise'])
|
|
293
|
-
.optional()
|
|
294
|
-
.describe('Organization size'),
|
|
295
|
-
contacts: z.array(z.string()).optional().describe('Related person wikilinks'),
|
|
296
|
-
projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
297
|
-
relationship_start: z.string().optional().describe('When the relationship started'),
|
|
298
|
-
notes: z.string().optional().describe('Additional notes (markdown)'),
|
|
299
|
-
});
|
|
300
|
-
/**
|
|
301
|
-
* Financial Plan entity - budgets, rates, forecasts
|
|
302
|
-
*/
|
|
303
|
-
export const FinancialPlanSchema = EntityBaseSchema.extend({
|
|
304
|
-
entity_type: z.literal('financial-plan'),
|
|
305
|
-
name: z.string().min(1, 'Financial plan name is required'),
|
|
306
|
-
type: z.enum(['budget', 'forecast', 'rates', 'compensation'])
|
|
307
|
-
.optional()
|
|
308
|
-
.describe('Plan type'),
|
|
309
|
-
period: z.string().optional().describe('Time period (e.g., Q1 2026, FY2026)'),
|
|
310
|
-
project: z.string().optional().describe('Related project wikilink'),
|
|
311
|
-
amounts: z.string().optional().describe('Financial amounts (markdown table)'),
|
|
266
|
+
.describe('Publication status'),
|
|
267
|
+
published_date: z.string().optional().describe('Date published'),
|
|
268
|
+
url: z.string().optional().describe('URL of published content'),
|
|
269
|
+
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
270
|
+
related_areas: z.array(z.string()).optional().describe('Related practice area wikilinks'),
|
|
312
271
|
});
|
|
313
272
|
/**
|
|
314
|
-
* Deal
|
|
315
|
-
*
|
|
316
|
-
* Distinct from a project (which is post-signing execution) and from a proposal
|
|
317
|
-
* (which is a document artifact). Multiple proposals can belong to one deal.
|
|
318
|
-
* When a deal is won, a project is created and linked via project.deal.
|
|
273
|
+
* Deal — pre-project opportunity in the sales pipeline
|
|
319
274
|
*/
|
|
320
275
|
export const DealSchema = EntityBaseSchema.extend({
|
|
321
276
|
entity_type: z.literal('deal'),
|
|
@@ -324,77 +279,22 @@ export const DealSchema = EntityBaseSchema.extend({
|
|
|
324
279
|
contacts: z.array(z.string()).optional().describe('Contact person wikilinks'),
|
|
325
280
|
stage: z.enum(['scoping', 'proposal', 'negotiating', 'won', 'lost'])
|
|
326
281
|
.default('scoping')
|
|
327
|
-
.describe('
|
|
328
|
-
deal_value: z.number().optional().describe('Estimated deal value
|
|
282
|
+
.describe('Pipeline stage'),
|
|
283
|
+
deal_value: z.number().optional().describe('Estimated deal value'),
|
|
329
284
|
probability: z.number().min(0).max(100).optional().describe('Win probability 0–100'),
|
|
330
|
-
expected_close: z.string().optional().describe('Expected close date
|
|
285
|
+
expected_close: z.string().optional().describe('Expected close date'),
|
|
331
286
|
source: z.enum(['referral', 'inbound', 'outbound', 'repeat', 'partner', 'other'])
|
|
332
287
|
.optional()
|
|
333
288
|
.describe('How the opportunity originated'),
|
|
334
|
-
proposals: z.array(z.string()).optional().describe('Related proposal wikilinks'),
|
|
289
|
+
proposals: z.array(z.string()).optional().describe('Related proposal document wikilinks'),
|
|
335
290
|
project: z.string().optional().describe('Resulting project wikilink (once won)'),
|
|
336
291
|
lost_reason: z.string().optional().describe('Why the deal was lost'),
|
|
337
292
|
});
|
|
293
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
294
|
+
// KNOWLEDGE ENTITIES — typically in resource repos
|
|
295
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
338
296
|
/**
|
|
339
|
-
*
|
|
340
|
-
*/
|
|
341
|
-
export const VendorSchema = EntityBaseSchema.extend({
|
|
342
|
-
entity_type: z.literal('vendor'),
|
|
343
|
-
name: z.string().min(1, 'Vendor name is required'),
|
|
344
|
-
type: z.enum(['freelancer', 'agency', 'supplier', 'platform', 'partner', 'other'])
|
|
345
|
-
.optional()
|
|
346
|
-
.describe('Vendor type'),
|
|
347
|
-
status: z.enum(['active', 'inactive', 'preferred'])
|
|
348
|
-
.default('active')
|
|
349
|
-
.describe('Vendor status'),
|
|
350
|
-
contact_name: z.string().optional().describe('Primary contact name'),
|
|
351
|
-
email: z.string().optional().describe('Contact email'),
|
|
352
|
-
website: z.string().url().optional().describe('Vendor website URL'),
|
|
353
|
-
services: z.array(z.string()).optional().describe('Services provided'),
|
|
354
|
-
projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
355
|
-
notes: z.string().optional().describe('Additional notes (markdown)'),
|
|
356
|
-
});
|
|
357
|
-
/**
|
|
358
|
-
* Role entity - generalized role definitions from the firm's leveling framework
|
|
359
|
-
*
|
|
360
|
-
* Body markdown holds: Role Overview, Key Responsibilities,
|
|
361
|
-
* Leveling Criteria (pillars), Required Skills.
|
|
362
|
-
*/
|
|
363
|
-
export const RoleSchema = EntityBaseSchema.extend({
|
|
364
|
-
entity_type: z.literal('role'),
|
|
365
|
-
title: z.string().min(1, 'Role title is required'),
|
|
366
|
-
department: z.string().optional().describe('Department (e.g. Creative Technology, Design)'),
|
|
367
|
-
level: z.number().optional().describe('Level 1–5 from leveling framework'),
|
|
368
|
-
type: z.enum(['staff', 'contractor', 'intern'])
|
|
369
|
-
.optional()
|
|
370
|
-
.describe('Employment type'),
|
|
371
|
-
status: z.enum(['active', 'archived'])
|
|
372
|
-
.default('active')
|
|
373
|
-
.describe('Role status'),
|
|
374
|
-
location: z.string().optional().describe('Location'),
|
|
375
|
-
reports_to: z.string().optional().describe('Parent role or person wikilink'),
|
|
376
|
-
});
|
|
377
|
-
/**
|
|
378
|
-
* SHARED RESOURCE REPO ENTITIES
|
|
379
|
-
* Used in shared knowledge repositories
|
|
380
|
-
*/
|
|
381
|
-
/**
|
|
382
|
-
* Template entity - document templates and boilerplates
|
|
383
|
-
*/
|
|
384
|
-
export const TemplateSchema = EntityBaseSchema.extend({
|
|
385
|
-
entity_type: z.literal('template'),
|
|
386
|
-
name: z.string().min(1, 'Template name is required'),
|
|
387
|
-
category: z.string()
|
|
388
|
-
.optional()
|
|
389
|
-
.describe('Template category (e.g., proposal, brief, sow, meeting-notes)'),
|
|
390
|
-
description: z.string().optional().describe('Template description'),
|
|
391
|
-
template_content: z.string().optional().describe('Template content (markdown)'),
|
|
392
|
-
variables: z.array(z.string())
|
|
393
|
-
.optional()
|
|
394
|
-
.describe('Template variables (e.g., {{project_name}})'),
|
|
395
|
-
});
|
|
396
|
-
/**
|
|
397
|
-
* Process entity - workflows and methodologies
|
|
297
|
+
* Process — workflows, SOPs, and methodologies
|
|
398
298
|
*/
|
|
399
299
|
export const ProcessSchema = EntityBaseSchema.extend({
|
|
400
300
|
entity_type: z.literal('process'),
|
|
@@ -402,146 +302,91 @@ export const ProcessSchema = EntityBaseSchema.extend({
|
|
|
402
302
|
description: z.string().optional().describe('Process description'),
|
|
403
303
|
steps: z.string().optional().describe('Process steps (markdown)'),
|
|
404
304
|
related_areas: z.array(z.string()).optional().describe('Related practice areas'),
|
|
405
|
-
related_templates: z.array(z.string()).optional().describe('Related template wikilinks'),
|
|
406
305
|
owner: z.string().optional().describe('Person or team responsible (wikilink)'),
|
|
407
|
-
review_cycle: z.enum(['monthly', 'quarterly', 'annual', 'as-needed']).optional().describe('
|
|
306
|
+
review_cycle: z.enum(['monthly', 'quarterly', 'annual', 'as-needed']).optional().describe('Review frequency'),
|
|
408
307
|
});
|
|
409
308
|
/**
|
|
410
|
-
* Standard
|
|
309
|
+
* Standard — guidelines and best practices
|
|
411
310
|
*/
|
|
412
311
|
export const StandardSchema = EntityBaseSchema.extend({
|
|
413
312
|
entity_type: z.literal('standard'),
|
|
414
313
|
name: z.string().min(1, 'Standard name is required'),
|
|
415
|
-
category: z.string()
|
|
416
|
-
.optional()
|
|
417
|
-
.describe('Standard category (e.g., accessibility, design-principles, code-standards)'),
|
|
314
|
+
category: z.string().optional().describe('Category (e.g., accessibility, design-principles, code-standards)'),
|
|
418
315
|
description: z.string().optional().describe('Standard description'),
|
|
419
316
|
guidelines: z.string().optional().describe('Guidelines (markdown)'),
|
|
420
317
|
examples: z.array(z.string()).optional().describe('Example wikilinks'),
|
|
421
318
|
});
|
|
422
319
|
/**
|
|
423
|
-
*
|
|
424
|
-
*/
|
|
425
|
-
export const ReferenceSchema = EntityBaseSchema.extend({
|
|
426
|
-
entity_type: z.literal('reference'),
|
|
427
|
-
name: z.string().min(1, 'Reference name is required'),
|
|
428
|
-
type: z.enum(['article', 'video', 'visualization', 'website', 'research', 'podcast', 'project', 'tool'])
|
|
429
|
-
.optional()
|
|
430
|
-
.describe('Reference type'),
|
|
431
|
-
date: z.string().optional().describe('Publication or creation date'),
|
|
432
|
-
source: z.string().optional().describe('Source/author'),
|
|
433
|
-
link: z.string().optional().describe('URL'),
|
|
434
|
-
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
435
|
-
related_people: z.array(z.string()).optional().describe('Related people wikilinks'),
|
|
436
|
-
related_areas: z.array(z.string()).optional().describe('Related practice areas'),
|
|
437
|
-
description: z.string().optional().describe('Reference description'),
|
|
438
|
-
});
|
|
439
|
-
/**
|
|
440
|
-
* Technique entity - methods and patterns
|
|
441
|
-
*/
|
|
442
|
-
export const TechniqueSchema = EntityBaseSchema.extend({
|
|
443
|
-
entity_type: z.literal('technique'),
|
|
444
|
-
name: z.string().min(1, 'Technique name is required'),
|
|
445
|
-
category: z.string()
|
|
446
|
-
.optional()
|
|
447
|
-
.describe('Technique category (e.g., visualization, interaction-pattern, data-structure)'),
|
|
448
|
-
description: z.string().optional().describe('Technique description'),
|
|
449
|
-
difficulty: z.enum(['beginner', 'intermediate', 'advanced'])
|
|
450
|
-
.optional()
|
|
451
|
-
.describe('Difficulty level'),
|
|
452
|
-
related_frameworks: z.array(z.string()).optional().describe('Related framework wikilinks'),
|
|
453
|
-
examples: z.array(z.string()).optional().describe('Example wikilinks'),
|
|
454
|
-
});
|
|
455
|
-
/**
|
|
456
|
-
* Practice Area entity - firm capabilities and disciplines
|
|
457
|
-
*/
|
|
458
|
-
export const PracticeAreaSchema = EntityBaseSchema.extend({
|
|
459
|
-
entity_type: z.literal('practice-area'),
|
|
460
|
-
name: z.string().min(1, 'Practice area name is required'),
|
|
461
|
-
description: z.string().optional().describe('Overview of the discipline'),
|
|
462
|
-
capabilities: z.array(z.string()).optional().describe('Specific service offerings'),
|
|
463
|
-
related_case_studies: z.array(z.string()).optional().describe('Case study wikilinks'),
|
|
464
|
-
related_projects: z.array(z.string()).optional().describe('Related project wikilinks'),
|
|
465
|
-
});
|
|
466
|
-
/**
|
|
467
|
-
* Case Study entity - portfolio narratives for completed projects
|
|
468
|
-
*
|
|
469
|
-
* Body markdown holds: Objective, Solution, Outcome, Team, Press, Awards.
|
|
320
|
+
* Case Study — portfolio narratives for completed projects
|
|
470
321
|
*/
|
|
471
322
|
export const CaseStudySchema = EntityBaseSchema.extend({
|
|
472
323
|
entity_type: z.literal('case-study'),
|
|
473
324
|
title: z.string().min(1, 'Case study title is required'),
|
|
474
|
-
client: z.string().optional().describe('Client wikilink'),
|
|
325
|
+
client: z.string().optional().describe('Client organization wikilink'),
|
|
475
326
|
year: z.number().optional().describe('Year of the project'),
|
|
476
327
|
practice_areas: z.array(z.string()).optional().describe('Practice area wikilinks'),
|
|
477
328
|
sectors: z.array(z.string()).optional().describe('Industry tags'),
|
|
478
329
|
website_url: z.string().url().optional().describe('Project website URL'),
|
|
479
|
-
description: z.string().optional().describe('Short description
|
|
330
|
+
description: z.string().optional().describe('Short description'),
|
|
480
331
|
});
|
|
332
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
333
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
334
|
+
// SCHEMA REGISTRY
|
|
335
|
+
// ══════════════════════════════════════════════════════════════════════════════
|
|
481
336
|
/**
|
|
482
|
-
*
|
|
483
|
-
|
|
484
|
-
export const ColumnDefinitionSchema = z.object({
|
|
485
|
-
name: z.string().min(1),
|
|
486
|
-
type: z.enum(['string', 'number', 'boolean', 'date']),
|
|
487
|
-
required: z.boolean().optional(),
|
|
488
|
-
description: z.string().optional(),
|
|
489
|
-
});
|
|
490
|
-
export const DatasetSchema = EntityBaseSchema.extend({
|
|
491
|
-
entity_type: z.literal('dataset'),
|
|
492
|
-
name: z.string().min(1, 'Dataset name is required'),
|
|
493
|
-
schema: z.array(ColumnDefinitionSchema).min(1, 'At least one column required'),
|
|
494
|
-
});
|
|
495
|
-
// ── App entity types ────────────────────────────────────────────────────────
|
|
496
|
-
/**
|
|
497
|
-
* Deck — presentation deck managed by the Schema Slides app plugin.
|
|
498
|
-
* The document body is the full slide markdown (HTML comment directives + slide content).
|
|
499
|
-
*/
|
|
500
|
-
export const DeckSchema = EntityBaseSchema.extend({
|
|
501
|
-
entity_type: z.literal('deck'),
|
|
502
|
-
title: z.string().min(1, 'Deck title is required'),
|
|
503
|
-
client: z.string().optional(),
|
|
504
|
-
date: z.string().min(1, 'Date is required'),
|
|
505
|
-
phase: z.string().optional(),
|
|
506
|
-
theme: z.enum(['dark', 'light']).default('dark'),
|
|
507
|
-
status: z.enum(['draft', 'review', 'approved']).default('draft'),
|
|
508
|
-
related_project: z.string().optional(),
|
|
509
|
-
related_client: z.string().optional(),
|
|
510
|
-
});
|
|
511
|
-
/**
|
|
512
|
-
* Schema registry - maps entity types to their schemas
|
|
337
|
+
* Maps entity types to their Zod schemas.
|
|
338
|
+
* 17 built-in types. App plugins register additional types at runtime via SchemaRegistry.
|
|
513
339
|
*/
|
|
514
340
|
export const ENTITY_SCHEMAS = {
|
|
515
|
-
//
|
|
341
|
+
// Identity (4)
|
|
342
|
+
person: PersonSchema,
|
|
343
|
+
organization: OrganizationSchema,
|
|
344
|
+
role: RoleSchema,
|
|
345
|
+
'practice-area': PracticeAreaSchema,
|
|
346
|
+
// Universal (10)
|
|
516
347
|
project: ProjectSchema,
|
|
517
348
|
meeting: MeetingSchema,
|
|
518
349
|
decision: DecisionSchema,
|
|
519
350
|
task: TaskSchema,
|
|
520
|
-
|
|
521
|
-
|
|
351
|
+
document: DocumentSchema,
|
|
352
|
+
dataset: DatasetSchema,
|
|
353
|
+
reference: ReferenceSchema,
|
|
354
|
+
note: NoteSchema,
|
|
522
355
|
deliverable: DeliverableSchema,
|
|
523
|
-
|
|
524
|
-
proposal: ProposalSchema,
|
|
525
|
-
contract: ContractSchema,
|
|
526
|
-
person: PersonSchema,
|
|
527
|
-
client: ClientSchema,
|
|
528
|
-
'financial-plan': FinancialPlanSchema,
|
|
356
|
+
publication: PublicationSchema,
|
|
529
357
|
deal: DealSchema,
|
|
530
|
-
|
|
531
|
-
role: RoleSchema,
|
|
532
|
-
// Shared resource repos
|
|
533
|
-
template: TemplateSchema,
|
|
358
|
+
// Knowledge (3)
|
|
534
359
|
process: ProcessSchema,
|
|
535
360
|
standard: StandardSchema,
|
|
536
|
-
reference: ReferenceSchema,
|
|
537
|
-
technique: TechniqueSchema,
|
|
538
|
-
'practice-area': PracticeAreaSchema,
|
|
539
361
|
'case-study': CaseStudySchema,
|
|
540
|
-
// Dataset
|
|
541
|
-
dataset: DatasetSchema,
|
|
542
|
-
// App entity types (registered by app plugins)
|
|
543
|
-
deck: DeckSchema,
|
|
544
362
|
};
|
|
363
|
+
/**
|
|
364
|
+
* Plural subfolder name → singular entity_type mapping
|
|
365
|
+
*/
|
|
366
|
+
export const PLURAL_TO_SINGULAR = {
|
|
367
|
+
'people': 'person',
|
|
368
|
+
'organizations': 'organization',
|
|
369
|
+
'roles': 'role',
|
|
370
|
+
'practice-areas': 'practice-area',
|
|
371
|
+
'projects': 'project',
|
|
372
|
+
'meetings': 'meeting',
|
|
373
|
+
'decisions': 'decision',
|
|
374
|
+
'tasks': 'task',
|
|
375
|
+
'documents': 'document',
|
|
376
|
+
'datasets': 'dataset',
|
|
377
|
+
'references': 'reference',
|
|
378
|
+
'notes': 'note',
|
|
379
|
+
'deliverables': 'deliverable',
|
|
380
|
+
'publications': 'publication',
|
|
381
|
+
'deals': 'deal',
|
|
382
|
+
'processes': 'process',
|
|
383
|
+
'standards': 'standard',
|
|
384
|
+
'case-studies': 'case-study',
|
|
385
|
+
};
|
|
386
|
+
/**
|
|
387
|
+
* Singular entity_type → plural subfolder name mapping
|
|
388
|
+
*/
|
|
389
|
+
export const SINGULAR_TO_PLURAL = Object.fromEntries(Object.entries(PLURAL_TO_SINGULAR).map(([plural, singular]) => [singular, plural]));
|
|
545
390
|
/**
|
|
546
391
|
* Validation helper with helpful error messages
|
|
547
392
|
*/
|
|
@@ -583,7 +428,7 @@ export function validateCustomEntity(data) {
|
|
|
583
428
|
}
|
|
584
429
|
}
|
|
585
430
|
/**
|
|
586
|
-
* Check if
|
|
431
|
+
* Check if a type is a known built-in entity type
|
|
587
432
|
*/
|
|
588
433
|
export function isKnownEntityType(type) {
|
|
589
434
|
return type in ENTITY_SCHEMAS;
|