@synap-core/workspace-templates 0.12.0 → 0.24.0
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 +509 -0
- package/automations/bookmark-enrichment.automation.json +321 -0
- package/automations/github-pr-events.automation.json +505 -0
- package/automations/mail-feed.automation.json +86 -0
- package/automations/ship-a-change-checks-green.automation.json +106 -0
- package/automations/ship-a-change-checks-red.automation.json +106 -0
- package/automations/ship-a-change-deployed.automation.json +56 -0
- package/automations/ship-a-change-pr-merged.automation.json +110 -0
- package/automations/ship-a-change-pr-opened.automation.json +104 -0
- package/automations/url-bookmark-capture.automation.json +132 -0
- package/capabilities/agency-skills.capability.json +157 -0
- package/capabilities/apify.capability.json +265 -0
- package/capabilities/apollo.capability.json +120 -0
- package/capabilities/arch-backend.capability.json +97 -0
- package/capabilities/arch-client-intelligence.capability.json +401 -0
- package/capabilities/backblaze-b2.capability.json +205 -0
- package/capabilities/cal-com.capability.json +266 -0
- package/capabilities/canva.capability.json +274 -0
- package/capabilities/claude-code-routines.capability.json +172 -0
- package/capabilities/claude-managed-agents.capability.json +215 -0
- package/capabilities/client-comms-report.capability.json +246 -0
- package/capabilities/content-idea-to-production.capability.json +29 -0
- package/capabilities/datagouv.capability.json +315 -0
- package/capabilities/discord-bot.capability.json +157 -0
- package/capabilities/dropbox.capability.json +281 -0
- package/capabilities/exa.capability.json +109 -0
- package/capabilities/fal-ai.capability.json +83 -0
- package/capabilities/fal-media-lab.capability.json +158 -0
- package/capabilities/fireflies.capability.json +191 -0
- package/capabilities/freellmapi.capability.json +114 -0
- package/capabilities/generic-apikey.capability.json +92 -0
- package/capabilities/github-merge.capability.json +99 -0
- package/capabilities/github-read.capability.json +325 -0
- package/capabilities/governance-tighten-recommender.capability.json +81 -0
- package/capabilities/jev.capability.json +226 -0
- package/capabilities/lead-conversion-enrollment.capability.json +246 -0
- package/capabilities/mail-feed.capability.json +277 -0
- package/capabilities/mailgun.capability.json +52 -0
- package/capabilities/nango-google.capability.json +639 -0
- package/capabilities/notion.capability.json +417 -0
- package/capabilities/omniroute.capability.json +137 -0
- package/capabilities/posthog-analytics.capability.json +258 -0
- package/capabilities/postiz.capability.json +467 -0
- package/capabilities/proactive-digest.capability.json +190 -0
- package/capabilities/proton.capability.json +288 -0
- package/capabilities/replicate-rvm.capability.json +97 -0
- package/capabilities/research-methods.capability.json +57 -0
- package/capabilities/shopify.capability.json +395 -0
- package/capabilities/slack.capability.json +369 -0
- package/capabilities/stripe.capability.json +1496 -0
- package/capabilities/telegram-bridge.capability.json +56 -0
- package/capabilities/treg.capability.json +102 -0
- package/capabilities/unipile-linkedin.capability.json +494 -0
- package/capabilities/vercel.capability.json +424 -0
- package/dist/define-DqoItRiR.d.ts +1370 -0
- package/dist/index.d.ts +174 -900
- package/dist/index.js +26447 -24075
- package/dist/index.js.map +1 -1
- package/dist/wire.d.ts +222 -0
- package/dist/wire.js +77 -0
- package/dist/wire.js.map +1 -0
- package/package.json +27 -4
- package/retired.yaml +136 -0
- package/skills/app-factory-build-slice/SKILL.md +70 -0
- package/skills/app-factory-build-slice.catalog.json +17 -0
- package/skills/app-factory-design-canvas/SKILL.md +96 -0
- package/skills/app-factory-design-canvas.catalog.json +17 -0
- package/skills/app-factory-design-review/SKILL.md +105 -0
- package/skills/app-factory-design-review.catalog.json +18 -0
- package/skills/app-factory-research/SKILL.md +123 -0
- package/skills/app-factory-research.catalog.json +17 -0
- package/skills/bookmark-enrichment/SKILL.md +40 -0
- package/skills/carousel-format/carousel-format.skill.json +18 -0
- package/skills/collage-broll/collage-broll.skill.json +20 -0
- package/skills/content-taste/content-taste.skill.json +18 -0
- package/skills/creative-director/creative-director.skill.json +18 -0
- package/skills/design-critique/SKILL.md +138 -0
- package/skills/design-critique.catalog.json +12 -0
- package/skills/designing-with-real-components/SKILL.md +140 -0
- package/skills/designing-with-real-components.catalog.json +12 -0
- package/skills/edit-loop/edit-loop.skill.json +25 -0
- package/skills/facecam-edit/facecam-edit.skill.json +24 -0
- package/skills/mapping-the-server/SKILL.md +54 -0
- package/skills/math-explainer-manimgx/math-explainer-manimgx.skill.json +20 -0
- package/skills/motion-quality-gates/motion-quality-gates.skill.json +20 -0
- package/skills/open-design-edit/open-design-edit.skill.json +24 -0
- package/skills/reading-client-progress/SKILL.md +65 -0
- package/skills/routing-to-channels/SKILL.md +54 -0
- package/skills/stellar-scf-grants-advisor/ASSOCIATE-CHEATSHEET.md +133 -0
- package/skills/stellar-scf-grants-advisor/ASSOCIATE-ONBOARDING-GUIDE.md +761 -0
- package/skills/stellar-scf-grants-advisor/CLIENT-FAQ.md +181 -0
- package/skills/stellar-scf-grants-advisor/PARTNER-HANDOVER.md +130 -0
- package/skills/stellar-scf-grants-advisor/SKILL.md +102 -0
- package/skills/stellar-scf-grants-advisor/examples/README.md +43 -0
- package/skills/stellar-scf-grants-advisor/examples/chat-summary-templates.md +158 -0
- package/skills/stellar-scf-grants-advisor/examples/corpus-comparable-rows.md +136 -0
- package/skills/stellar-scf-grants-advisor/examples/q10-team-rewrites.md +109 -0
- package/skills/stellar-scf-grants-advisor/examples/q2-description-rewrites.md +88 -0
- package/skills/stellar-scf-grants-advisor/examples/q6-integration-rewrites.md +107 -0
- package/skills/stellar-scf-grants-advisor/examples/tranche-structures.md +176 -0
- package/skills/stellar-scf-grants-advisor/reference/01-methodology.md +96 -0
- package/skills/stellar-scf-grants-advisor/reference/02-scoring-framework.md +199 -0
- package/skills/stellar-scf-grants-advisor/reference/03-rejection-patterns.md +241 -0
- package/skills/stellar-scf-grants-advisor/reference/04-winner-patterns.md +120 -0
- package/skills/stellar-scf-grants-advisor/reference/05-comeback-patterns.md +92 -0
- package/skills/stellar-scf-grants-advisor/reference/06-budget-benchmarks.md +125 -0
- package/skills/stellar-scf-grants-advisor/reference/07-integration-list.md +147 -0
- package/skills/stellar-scf-grants-advisor/reference/08-abstract-fields.md +258 -0
- package/skills/stellar-scf-grants-advisor/reference/09-build-fields.md +259 -0
- package/skills/stellar-scf-grants-advisor/reference/10-corpus-winners.md +135 -0
- package/skills/stellar-scf-grants-advisor/reference/11-corpus-rejects.md +267 -0
- package/skills/stellar-scf-grants-advisor/reference/12-client-communication.md +131 -0
- package/skills/stellar-scf-grants-advisor/reference/13-excel-output-spec.md +199 -0
- package/skills/stellar-scf-grants-advisor/reference/14-worked-examples.md +160 -0
- package/skills/stellar-scf-grants-advisor/templates/abstract-review-builder.py +253 -0
- package/skills/stellar-scf-grants-advisor/templates/build-review-builder.py +213 -0
- package/skills/video-direction/video-direction.skill.json +20 -0
- package/skills/video-style-vocabulary/video-style-vocabulary.skill.json +20 -0
- package/skills/video-toolbox/video-toolbox.skill.json +20 -0
- package/src/__fixtures__/lifecycle-presets.flat-before.json +205 -0
- package/src/agency-os.yaml +122 -0
- package/src/agent-os-skill-slugs.test.ts +65 -0
- package/src/apify-social-reader.test.ts +317 -0
- package/src/base.yaml +85 -39
- package/src/blockchain-ecosystem.yaml +1 -0
- package/src/brand-library.yaml +525 -14
- package/src/builder-dev-fold.template.test.ts +113 -0
- package/src/builder.yaml +779 -91
- package/src/business-model-catalog-description.test.ts +47 -0
- package/src/business-model-grp.template.test.ts +214 -0
- package/src/business-model.yaml +296 -49
- package/src/catalog-safety.test.ts +198 -0
- package/src/catalog.template-items.test.ts +75 -0
- package/src/catalog.ts +66 -2
- package/src/concept-guard.test.ts +28 -8
- package/src/concept-guard.ts +2 -2
- package/src/content-creation.template.test.ts +52 -0
- package/src/content-creation.yaml +192 -0
- package/src/content-os.edit-loop.template.test.ts +210 -0
- package/src/content-os.publish-due-posts.template.test.ts +261 -0
- package/src/content-os.template.test.ts +349 -0
- package/src/content-os.video-takes.template.test.ts +338 -0
- package/src/content-os.work-a-take.template.test.ts +125 -0
- package/src/content-os.yaml +1873 -39
- package/src/content-studio-retired.template.test.ts +82 -0
- package/src/corpus-flow-validity.test.ts +4 -5
- package/src/crm-absorbs-outreach.template.test.ts +117 -0
- package/src/crm-build-plan.template.test.ts +128 -0
- package/src/crm-lists.template.test.ts +96 -0
- package/src/crm-messages-cadence.template.test.ts +246 -0
- package/src/crm-one-send-door.template.test.ts +65 -0
- package/src/crm.yaml +1563 -181
- package/src/decisions-wave.template.test.ts +186 -0
- package/src/define.ts +146 -17
- package/src/design-to-implementation.template.test.ts +94 -0
- package/src/domain-template-type.test.ts +75 -0
- package/src/ecosystem.yaml +27 -66
- package/src/enterprise-os.yaml +10 -134
- package/src/facecam-edit.audio-studio.test.ts +188 -0
- package/src/fal-generate-image.test.ts +200 -0
- package/src/fal-media-lab-pod-files.test.ts +180 -0
- package/src/finance.yaml +254 -1
- package/src/foundation.yaml +78 -38
- package/src/frame-host-modules.d.mts +6 -0
- package/src/frame-host-modules.mjs +58 -0
- package/src/generate.mjs +9 -3
- package/src/github-merge.test.ts +210 -0
- package/src/grants.yaml +46 -17
- package/src/hr.yaml +39 -6
- package/src/index.ts +36 -1
- package/src/intent.test.ts +161 -0
- package/src/internal-runbook.yaml +19 -1
- package/src/jev.test.ts +356 -0
- package/src/legal.yaml +33 -1
- package/src/life-os.yaml +51 -240
- package/src/lifecycle-coverage.test.ts +124 -0
- package/src/lifecycle-declarations.test.ts +252 -0
- package/src/lifecycle-presets.test.ts +468 -0
- package/src/lifecycle-presets.ts +494 -0
- package/src/lifecycle-stuck.test.ts +46 -0
- package/src/lifecycle-waits.parity.test.ts +319 -0
- package/src/marketing.yaml +108 -4
- package/src/meetings-knowledge.yaml +18 -0
- package/src/networking.yaml +23 -2
- package/src/operations.yaml +304 -4
- package/src/pipeline-views.template.test.ts +88 -0
- package/src/playbook-goal-placeholders.test.ts +57 -0
- package/src/postiz-contract.test.ts +134 -0
- package/src/presentation-declarations.test.ts +174 -0
- package/src/process-contract.validate.test.ts +352 -0
- package/src/project-management.yaml +39 -740
- package/src/publish-body.d.mts +29 -0
- package/src/publish-body.mjs +74 -0
- package/src/publish-body.test.ts +74 -0
- package/src/publish-official-lib.test.ts +176 -0
- package/src/replicate-rvm.test.ts +504 -0
- package/src/research-base.yaml +119 -20
- package/src/research-decision.yaml +60 -3
- package/src/reserved-profile-slugs.test.ts +81 -0
- package/src/retired-goal-kinds.test.ts +52 -0
- package/src/role-reference-and-step-domain.test.ts +192 -0
- package/src/seed-obligation.test.ts +1 -6
- package/src/send-message-maps.test.ts +227 -0
- package/src/shared-role-ssot.test.ts +40 -2
- package/src/ship-a-change.template.test.ts +177 -0
- package/src/skills.test.ts +170 -0
- package/src/social.yaml +85 -27
- package/src/space-packages.freshness.test.ts +97 -0
- package/src/space-packages.generated.ts +40 -0
- package/src/space-packages.test.ts +125 -0
- package/src/space-packages.ts +73 -0
- package/src/start.test.ts +188 -0
- package/src/stripe-capability.test.ts +192 -0
- package/src/task-intents.test.ts +293 -0
- package/src/template-documents.test.ts +158 -0
- package/src/templates.ts +20907 -21464
- package/src/types.ts +475 -61
- package/src/unipile-linkedin-find-profile.test.ts +183 -0
- package/src/unipile-publish-post.test.ts +162 -0
- package/src/validate-flow.drift.test.ts +2 -3
- package/src/validate-flow.ts +22 -2
- package/src/validate-onboarding.test.ts +59 -0
- package/src/validate.test.ts +71 -4
- package/src/validate.ts +1416 -7
- package/src/wire-core.ts +231 -0
- package/src/wire.test.ts +159 -0
- package/src/wire.ts +107 -0
- package/views/bookmark-views-pack.view.json +39 -0
- package/views/event-views-pack.view.json +45 -0
- package/views/task-views-pack.view.json +53 -0
- package/src/agent-fleet.yaml +0 -1645
- package/src/business-developer.template.test.ts +0 -351
- package/src/business-developer.yaml +0 -860
- package/src/content-studio.yaml +0 -361
- package/src/dev-dashboard.yaml +0 -990
- package/src/outreach-comms.yaml +0 -486
- package/src/the-arch.yaml +0 -201
package/src/hr.yaml
CHANGED
|
@@ -13,6 +13,12 @@ meta:
|
|
|
13
13
|
color: "#E8663D"
|
|
14
14
|
tags: [hr, people, hiring, team]
|
|
15
15
|
isPublic: true
|
|
16
|
+
# What this space PRODUCES (homes): the purpose word, then its kinds/roles.
|
|
17
|
+
intent:
|
|
18
|
+
label: Team
|
|
19
|
+
produces:
|
|
20
|
+
- profile: candidate
|
|
21
|
+
- profile: review
|
|
16
22
|
|
|
17
23
|
workspace:
|
|
18
24
|
name: People
|
|
@@ -20,7 +26,10 @@ workspace:
|
|
|
20
26
|
proposalId: hr-v1
|
|
21
27
|
subtype: hr
|
|
22
28
|
visibility: members
|
|
23
|
-
|
|
29
|
+
# A DOMAIN workspace that holds entities — NOT `operational`. `operational`
|
|
30
|
+
# marks an admin/system surface: `isDomainHomeWorkspace` refuses filing
|
|
31
|
+
# entities into it and excludes it from auto-placement (2026-09-25).
|
|
32
|
+
workspaceType: personal
|
|
24
33
|
capabilities:
|
|
25
34
|
- hr.team
|
|
26
35
|
- hr.hiring
|
|
@@ -153,6 +162,17 @@ profiles:
|
|
|
153
162
|
profileKind: role
|
|
154
163
|
applicableKinds:
|
|
155
164
|
- person
|
|
165
|
+
# The ONE lifecycle (work model L1): every option's category.
|
|
166
|
+
lifecycle:
|
|
167
|
+
property: stage
|
|
168
|
+
options:
|
|
169
|
+
- { key: applied, category: open }
|
|
170
|
+
- { key: screening, category: active }
|
|
171
|
+
- { key: interview, category: active }
|
|
172
|
+
- { key: offer, category: active }
|
|
173
|
+
- { key: hired, category: done }
|
|
174
|
+
- { key: rejected, category: lost }
|
|
175
|
+
- { key: withdrawn, category: lost }
|
|
156
176
|
properties:
|
|
157
177
|
- slug: stage
|
|
158
178
|
label: Stage
|
|
@@ -195,6 +215,16 @@ profiles:
|
|
|
195
215
|
icon: clipboard-check
|
|
196
216
|
color: violet
|
|
197
217
|
description: "A performance review within a company review cycle."
|
|
218
|
+
# The ONE lifecycle (work model L1): every option's category.
|
|
219
|
+
lifecycle:
|
|
220
|
+
property: status
|
|
221
|
+
options:
|
|
222
|
+
- { key: not-started, category: open }
|
|
223
|
+
- { key: self-review, category: active }
|
|
224
|
+
- { key: manager-review, category: active }
|
|
225
|
+
- { key: calibration, category: active }
|
|
226
|
+
- { key: shared, category: active }
|
|
227
|
+
- { key: complete, category: done }
|
|
198
228
|
properties:
|
|
199
229
|
- slug: cycle
|
|
200
230
|
label: Cycle
|
|
@@ -315,13 +345,13 @@ views:
|
|
|
315
345
|
]
|
|
316
346
|
- name: Hiring Pipeline
|
|
317
347
|
slug: hiring-pipeline
|
|
318
|
-
|
|
348
|
+
# The ONE board (work model L3, D3): columns ARE the candidate role's
|
|
349
|
+
# declared lifecycle (`stage`), moves go through the one mover.
|
|
350
|
+
type: pipeline
|
|
319
351
|
scopeProfileSlug: candidate
|
|
320
|
-
groupBy: stage
|
|
321
|
-
description: Candidates moving through the pipeline, by stage.
|
|
322
352
|
config:
|
|
323
|
-
|
|
324
|
-
|
|
353
|
+
profileSlug: candidate
|
|
354
|
+
description: Candidates moving through the pipeline, by stage.
|
|
325
355
|
- name: Open Roles
|
|
326
356
|
slug: open-roles
|
|
327
357
|
type: table
|
|
@@ -430,10 +460,12 @@ onboarding:
|
|
|
430
460
|
30/60/90 plan rather than ambiguity.
|
|
431
461
|
collect:
|
|
432
462
|
- profileSlug: team-member
|
|
463
|
+
min: 1
|
|
433
464
|
what: The people currently on the team, with their role, department, and status.
|
|
434
465
|
cardinality: several
|
|
435
466
|
keyFields: [role-title, department, status]
|
|
436
467
|
- profileSlug: role
|
|
468
|
+
min: 1
|
|
437
469
|
what: The positions you're hiring for right now — open reqs with their hiring bar.
|
|
438
470
|
cardinality: few
|
|
439
471
|
keyFields: [status, department, seniority]
|
|
@@ -442,6 +474,7 @@ onboarding:
|
|
|
442
474
|
cardinality: few
|
|
443
475
|
keyFields: [stage, source]
|
|
444
476
|
- profileSlug: review
|
|
477
|
+
min: 1
|
|
445
478
|
what: The current review cycle and how you run performance (cadence + rubric).
|
|
446
479
|
cardinality: one
|
|
447
480
|
keyFields: [cycle, status]
|
package/src/index.ts
CHANGED
|
@@ -50,13 +50,26 @@ export type {
|
|
|
50
50
|
TemplatePlaybookParam,
|
|
51
51
|
TemplateAutomation,
|
|
52
52
|
TemplateActionPlacement,
|
|
53
|
+
TemplateIntent,
|
|
54
|
+
TemplateSpacePackage,
|
|
55
|
+
TemplateSpacePackageCell,
|
|
53
56
|
} from "./types.js";
|
|
54
57
|
|
|
58
|
+
// A template's space package: its built frame modules (the base layer of the
|
|
59
|
+
// space's own experience, installed as `cell:<slug>:<key>`).
|
|
60
|
+
export { spacePackageCells } from "./space-packages.js";
|
|
61
|
+
export type {
|
|
62
|
+
BuiltSpacePackage,
|
|
63
|
+
BuiltSpacePackageCell,
|
|
64
|
+
SpacePackageCellWire,
|
|
65
|
+
} from "./space-packages.js";
|
|
66
|
+
|
|
55
67
|
// The dependency-kind vocabulary as a VALUE — so consumers (marketplace,
|
|
56
68
|
// onboarding, backend, hub zod, browser, CP zod) can `z.enum(PACKAGE_DEPENDENCY_KINDS)`
|
|
57
69
|
// / derive their type from it instead of hand-copying the list. Six mirrors
|
|
58
70
|
// exist today; this is the door that lets them stop being mirrors.
|
|
59
|
-
export { PACKAGE_DEPENDENCY_KINDS } from "./types.js";
|
|
71
|
+
export { PACKAGE_DEPENDENCY_KINDS, INTENT_LABEL_MAX, START_VIEWS_MAX, START_EXAMPLE_RANGE, START_STARTERS_RANGE } from "./types.js";
|
|
72
|
+
export type { TemplateStart } from "./types.js";
|
|
60
73
|
|
|
61
74
|
export {
|
|
62
75
|
WORKSPACE_TEMPLATES,
|
|
@@ -73,6 +86,9 @@ export {
|
|
|
73
86
|
assembleCatalog,
|
|
74
87
|
computeTemplateUpdates,
|
|
75
88
|
isHashVersion,
|
|
89
|
+
derivePlaybookItems,
|
|
90
|
+
TRACK_TEMPLATE_ITEM_KIND,
|
|
91
|
+
WORK_TEMPLATE_ITEM_KIND,
|
|
76
92
|
} from "./catalog.js";
|
|
77
93
|
export type {
|
|
78
94
|
MergeCatalogInput,
|
|
@@ -133,6 +149,11 @@ export {
|
|
|
133
149
|
SYSTEM_PROFILES,
|
|
134
150
|
REQUIRED_META_FIELDS,
|
|
135
151
|
REQUIRED_WORKSPACE_FIELDS,
|
|
152
|
+
lifecycleOptionWaitsProblems,
|
|
153
|
+
LIFECYCLE_OPTION_FIELDS,
|
|
154
|
+
LIFECYCLE_OPTION_WAITS_FIELDS,
|
|
155
|
+
LIFECYCLE_WAITS_ON,
|
|
156
|
+
LIFECYCLE_WAIT_KINDS,
|
|
136
157
|
} from "./validate.js";
|
|
137
158
|
export type {
|
|
138
159
|
ValidationError,
|
|
@@ -141,6 +162,18 @@ export type {
|
|
|
141
162
|
TemplateConverters,
|
|
142
163
|
} from "./validate.js";
|
|
143
164
|
|
|
165
|
+
// The ten base lifecycles as template-time presets (`lifecycle.adopts`) and the
|
|
166
|
+
// ONE compiler that turns them into the flat declaration the pod stores. The
|
|
167
|
+
// catalog loader (scripts/catalog-lib.mjs) compiles authored YAML through it.
|
|
168
|
+
export { BASE_LIFECYCLES, resolveLifecyclePresets } from "./lifecycle-presets.js";
|
|
169
|
+
export type {
|
|
170
|
+
BaseLifecycleName,
|
|
171
|
+
TemplateLifecycleAdoption,
|
|
172
|
+
TemplateLifecycleStepAdd,
|
|
173
|
+
LifecyclePresetProblem,
|
|
174
|
+
LifecyclePresetResolution,
|
|
175
|
+
} from "./lifecycle-presets.js";
|
|
176
|
+
|
|
144
177
|
// The pure, DB-free automation-flow node-contract validator. `validateTemplate`
|
|
145
178
|
// runs it over every `automations[].flow` so broken flows (unknown node type,
|
|
146
179
|
// dangling edge, cycle, typo'd channelType, verb-less capability node) fail at
|
|
@@ -165,6 +198,7 @@ export {
|
|
|
165
198
|
toPackageDefinition,
|
|
166
199
|
splitBentoBlocks,
|
|
167
200
|
normalizeTemplateLayout,
|
|
201
|
+
toAutomationWire,
|
|
168
202
|
} from "./define.js";
|
|
169
203
|
export type {
|
|
170
204
|
WorkspaceDefinitionInput,
|
|
@@ -173,4 +207,5 @@ export type {
|
|
|
173
207
|
SplitBentoBlocks,
|
|
174
208
|
BentoWidgetBlockWire,
|
|
175
209
|
BentoViewBlockWire,
|
|
210
|
+
PackageAutomationWire,
|
|
176
211
|
} from "./define.js";
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `meta.intent` — what a space PRODUCES (object-first homes H0).
|
|
3
|
+
*
|
|
4
|
+
* Pinned:
|
|
5
|
+
* - each `intent-*` rule fires on a minimal broken template and stays silent
|
|
6
|
+
* on the fixed one (label length, unknown profile, profile without a
|
|
7
|
+
* lifecycle, duplicate, shape);
|
|
8
|
+
* - a produced profile may come from the dependency closure, and its
|
|
9
|
+
* lifecycle may be declared there (a role foundation owns);
|
|
10
|
+
* - (the catalog header half lives in `schema/intent-header.test.ts`);
|
|
11
|
+
* - BOTH install doors carry it (top-level `intent` on both), driven through
|
|
12
|
+
* the real converters.
|
|
13
|
+
*/
|
|
14
|
+
import { describe, expect, it } from "vitest";
|
|
15
|
+
import { validateTemplate } from "./validate.js";
|
|
16
|
+
import { toPackageDefinition, toWorkspaceDefinition } from "./define.js";
|
|
17
|
+
import type { TemplateIntent, TemplateProfile, WorkspaceYaml } from "./types.js";
|
|
18
|
+
import { INTENT_LABEL_MAX } from "./types.js";
|
|
19
|
+
import { readYamlTemplates } from "./generate.mjs";
|
|
20
|
+
|
|
21
|
+
const lifecycled = (slug: string): TemplateProfile => ({
|
|
22
|
+
slug,
|
|
23
|
+
displayName: slug,
|
|
24
|
+
properties: [{ slug: "stage", label: "Stage", valueType: "string", inputType: "select", enumValues: ["a", "b"] }],
|
|
25
|
+
lifecycle: { property: "stage", options: [{ key: "a", category: "open" }, { key: "b", category: "done" }] },
|
|
26
|
+
} as TemplateProfile);
|
|
27
|
+
const plain = (slug: string): TemplateProfile => ({ slug, displayName: slug, properties: [] } as unknown as TemplateProfile);
|
|
28
|
+
|
|
29
|
+
const make = (slug: string, profiles: TemplateProfile[], intent?: TemplateIntent, deps: string[] = []): WorkspaceYaml =>
|
|
30
|
+
({
|
|
31
|
+
meta: { slug, name: slug, description: "d", icon: "box", color: "blue", ...(intent ? { intent } : {}) },
|
|
32
|
+
workspace: { name: slug, description: "d" },
|
|
33
|
+
profiles,
|
|
34
|
+
dependencies: deps.map((d) => ({ slug: d, relation: "require" as const })),
|
|
35
|
+
}) as WorkspaceYaml;
|
|
36
|
+
|
|
37
|
+
const base = make("base-dep", [lifecycled("role-x"), plain("bare-dep")]);
|
|
38
|
+
const resolveDep = (s: string) => (s === "base-dep" ? base : undefined);
|
|
39
|
+
const intentErrors = (t: WorkspaceYaml) =>
|
|
40
|
+
validateTemplate(t, { resolveDep }).errors.filter((e) => e.rule.startsWith("intent-"));
|
|
41
|
+
|
|
42
|
+
describe("meta.intent — validator rules", () => {
|
|
43
|
+
it("a well-formed intent (own kind + a dependency's role) passes", () => {
|
|
44
|
+
const t = make("t", [lifecycled("thing")], { label: "Product", produces: [{ profile: "thing" }, { profile: "role-x" }] }, ["base-dep"]);
|
|
45
|
+
expect(intentErrors(t)).toEqual([]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("a library (label only, or empty produces) passes", () => {
|
|
49
|
+
expect(intentErrors(make("t", [plain("x")], { label: "Library" }))).toEqual([]);
|
|
50
|
+
expect(intentErrors(make("t", [plain("x")], { label: "Library", produces: [] }))).toEqual([]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("intent-label: empty or longer than the max is refused", () => {
|
|
54
|
+
expect(intentErrors(make("t", [plain("x")], { label: "" })).map((e) => e.rule)).toEqual(["intent-label"]);
|
|
55
|
+
const long = "x".repeat(INTENT_LABEL_MAX + 1);
|
|
56
|
+
expect(intentErrors(make("t", [plain("x")], { label: long })).map((e) => e.rule)).toEqual(["intent-label"]);
|
|
57
|
+
expect(intentErrors(make("t", [plain("x")], { label: "x".repeat(INTENT_LABEL_MAX) }))).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("intent-profile-unknown: a profile neither own nor in the closure", () => {
|
|
61
|
+
const errs = intentErrors(make("t", [lifecycled("thing")], { label: "P", produces: [{ profile: "ghost" }] }));
|
|
62
|
+
expect(errs.map((e) => e.rule)).toEqual(["intent-profile-unknown"]);
|
|
63
|
+
expect(errs[0]!.message).toContain('"ghost"');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("intent-profile-unknown: a dependency's profile is NOT reachable without the dependency", () => {
|
|
67
|
+
const errs = intentErrors(make("t", [lifecycled("thing")], { label: "P", produces: [{ profile: "role-x" }] }));
|
|
68
|
+
expect(errs.map((e) => e.rule)).toEqual(["intent-profile-unknown"]);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("intent-no-lifecycle: names the produced profile that declares none", () => {
|
|
72
|
+
const own = intentErrors(make("t", [plain("thing")], { label: "P", produces: [{ profile: "thing" }] }));
|
|
73
|
+
expect(own.map((e) => e.rule)).toEqual(["intent-no-lifecycle"]);
|
|
74
|
+
expect(own[0]!.message).toContain('"thing"');
|
|
75
|
+
const dep = intentErrors(make("t", [lifecycled("thing")], { label: "P", produces: [{ profile: "bare-dep" }] }, ["base-dep"]));
|
|
76
|
+
expect(dep.map((e) => e.rule)).toEqual(["intent-no-lifecycle"]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("a re-declaration without the lifecycle still counts the dependency's declaration", () => {
|
|
80
|
+
const t = make("t", [plain("role-x")], { label: "P", produces: [{ profile: "role-x" }] }, ["base-dep"]);
|
|
81
|
+
expect(intentErrors(t)).toEqual([]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("intent-duplicate and intent-shape", () => {
|
|
85
|
+
const dup = intentErrors(make("t", [lifecycled("thing")], { label: "P", produces: [{ profile: "thing" }, { profile: "thing" }] }));
|
|
86
|
+
expect(dup.map((e) => e.rule)).toEqual(["intent-duplicate"]);
|
|
87
|
+
const shape = intentErrors(make("t", [lifecycled("thing")], { label: "P", produces: "thing" } as unknown as TemplateIntent));
|
|
88
|
+
expect(shape.map((e) => e.rule)).toEqual(["intent-shape"]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("intent-no-workspace: an overlay or a pack declares no intent", () => {
|
|
92
|
+
const overlay = make("t", [lifecycled("thing")], { label: "P" });
|
|
93
|
+
overlay.dependencies = [{ slug: "base-dep", relation: "compose" }];
|
|
94
|
+
expect(intentErrors(overlay).map((e) => e.rule)).toEqual(["intent-no-workspace"]);
|
|
95
|
+
const pack = make("t", [lifecycled("thing")], { label: "P" });
|
|
96
|
+
pack.meta.tags = ["suite"];
|
|
97
|
+
expect(intentErrors(pack).map((e) => e.rule)).toEqual(["intent-no-workspace"]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("an unresolvable dependency does not fabricate an unknown-profile error", () => {
|
|
101
|
+
const t = make("t", [lifecycled("thing")], { label: "P", produces: [{ profile: "elsewhere" }] }, ["not-in-corpus"]);
|
|
102
|
+
expect(intentErrors(t)).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("meta.intent — both install doors carry it", () => {
|
|
107
|
+
const intent = { label: "Product", produces: [{ profile: "thing" }] };
|
|
108
|
+
const t = make("t", [lifecycled("thing")], intent);
|
|
109
|
+
|
|
110
|
+
it("package door: top-level intent, never in _meta (the CP rebuilds _meta on serve)", () => {
|
|
111
|
+
const def = toPackageDefinition(t);
|
|
112
|
+
expect(def.intent).toEqual(intent);
|
|
113
|
+
expect("intent" in def._meta).toBe(false);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("workspace door: intent", () => {
|
|
117
|
+
expect(toWorkspaceDefinition(t).definition.intent).toEqual(intent);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("no intent → no field on either door", () => {
|
|
121
|
+
const none = make("t", [lifecycled("thing")]);
|
|
122
|
+
expect("intent" in toPackageDefinition(none)).toBe(false);
|
|
123
|
+
expect(toWorkspaceDefinition(none).definition.intent).toBeUndefined();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe("meta.intent — the catalog", () => {
|
|
128
|
+
const corpus = readYamlTemplates().map((t) => t.data as WorkspaceYaml);
|
|
129
|
+
const table = Object.fromEntries(
|
|
130
|
+
corpus
|
|
131
|
+
.filter((t) => t.meta.intent)
|
|
132
|
+
.map((t) => [t.meta.slug, [t.meta.intent!.label, ...(t.meta.intent!.produces ?? []).map((p) => p.profile)]])
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
it("the whole corpus validates with zero intent-* errors", () => {
|
|
136
|
+
const errs = corpus.flatMap((t) =>
|
|
137
|
+
validateTemplate(t, { corpus }).errors.filter((e) => e.rule.startsWith("intent-")).map((e) => `${t.meta.slug} ${e.rule}: ${e.message}`)
|
|
138
|
+
);
|
|
139
|
+
expect(errs).toEqual([]);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it("the founder's table (homes plan §1), in produces order", () => {
|
|
143
|
+
expect(table["builder-workspace"]).toEqual(["Product", "devplane_feature", "devplane_story", "ui-design"]);
|
|
144
|
+
// outreach-touch joined when CRM absorbed Outreach & Comms (founder decision 2026-10-23):
|
|
145
|
+
// the messages drafted for a person to send are part of the commercial job.
|
|
146
|
+
expect(table["crm"]).toEqual(["Sales", "lead", "client", "deal", "campaign", "outreach-touch"]);
|
|
147
|
+
expect(table["operations"]).toEqual(["Delivery", "engagement", "deliverable"]);
|
|
148
|
+
expect(table["content-os"]).toEqual(["Content", "post", "newsletter", "campaign"]);
|
|
149
|
+
expect(table["finance"]).toEqual(["Finance", "invoice", "expense"]);
|
|
150
|
+
expect(table["research-base"]).toEqual(["Research", "hypothesis", "finding"]);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("libraries carry a label only; overlays and packs carry none", () => {
|
|
154
|
+
for (const slug of ["brand-library", "foundation", "ecosystem"]) expect(table[slug], slug).toHaveLength(1);
|
|
155
|
+
for (const t of corpus) {
|
|
156
|
+
const ownsNone =
|
|
157
|
+
(t.dependencies ?? []).some((d) => d.relation === "compose") || (t.meta.tags ?? []).includes("suite");
|
|
158
|
+
if (ownsNone) expect(t.meta.intent, t.meta.slug).toBeUndefined();
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -14,6 +14,9 @@ meta:
|
|
|
14
14
|
color: "#64748B"
|
|
15
15
|
tags: [operations, sops, vendors, workflows]
|
|
16
16
|
isPublic: true
|
|
17
|
+
# A LIBRARY: it produces nothing a home counts (homes).
|
|
18
|
+
intent:
|
|
19
|
+
label: Runbook
|
|
17
20
|
|
|
18
21
|
workspace:
|
|
19
22
|
name: Internal Runbook
|
|
@@ -26,7 +29,10 @@ workspace:
|
|
|
26
29
|
# operations), so it must own its own identity.
|
|
27
30
|
subtype: internal-runbook
|
|
28
31
|
visibility: members
|
|
29
|
-
|
|
32
|
+
# A DOMAIN workspace that holds entities — NOT `operational`. `operational`
|
|
33
|
+
# marks an admin/system surface: `isDomainHomeWorkspace` refuses filing
|
|
34
|
+
# entities into it and excludes it from auto-placement (2026-09-25).
|
|
35
|
+
workspaceType: personal
|
|
30
36
|
capabilities:
|
|
31
37
|
- operations.sops
|
|
32
38
|
- operations.vendors
|
|
@@ -90,6 +96,15 @@ profiles:
|
|
|
90
96
|
color: "#0EA5E9"
|
|
91
97
|
description: "A recurring business process — a repeatable flow with an owner, a cadence, and an input/output."
|
|
92
98
|
scope: WORKSPACE
|
|
99
|
+
# The ONE lifecycle (work model L1): every option's category.
|
|
100
|
+
lifecycle:
|
|
101
|
+
property: workflow-status
|
|
102
|
+
options:
|
|
103
|
+
- { key: Backlog, category: open }
|
|
104
|
+
- { key: Active, category: active }
|
|
105
|
+
- { key: Blocked, category: paused }
|
|
106
|
+
- { key: Optimizing, category: active }
|
|
107
|
+
- { key: Retired, category: lost }
|
|
93
108
|
properties:
|
|
94
109
|
- slug: workflow-status
|
|
95
110
|
label: Status
|
|
@@ -423,14 +438,17 @@ onboarding:
|
|
|
423
438
|
person's head.
|
|
424
439
|
collect:
|
|
425
440
|
- profileSlug: sop
|
|
441
|
+
min: 1
|
|
426
442
|
what: The core documented procedures / runbooks — the repeatable ways of doing key things.
|
|
427
443
|
cardinality: several
|
|
428
444
|
keyFields: [title, category, owner, sop-status]
|
|
429
445
|
- profileSlug: workflow
|
|
446
|
+
min: 1
|
|
430
447
|
what: The recurring processes that run the business, each with an owner and a cadence.
|
|
431
448
|
cardinality: several
|
|
432
449
|
keyFields: [title, workflow-status, frequency, owner]
|
|
433
450
|
- profileSlug: vendor
|
|
451
|
+
min: 1
|
|
434
452
|
what: The suppliers and service providers the company pays and depends on.
|
|
435
453
|
cardinality: few
|
|
436
454
|
keyFields: [title, vendor-category, monthly-cost, owner]
|