@synap-core/workspace-templates 0.11.0 → 0.23.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 +483 -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 +420 -0
- package/capabilities/telegram-bridge.capability.json +56 -0
- package/capabilities/treg.capability.json +102 -0
- package/capabilities/unipile-linkedin.capability.json +471 -0
- package/capabilities/vercel.capability.json +424 -0
- package/dist/define-CPS0n8BV.d.ts +1331 -0
- package/dist/index.d.ts +189 -900
- package/dist/index.js +24654 -21639
- 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 +41 -27
- package/packs/bookmark-views-pack.json +33 -0
- package/packs/crm-pack.json +76 -0
- package/packs/customer-profile.json +28 -0
- package/packs/deep-research.playbook.json +30 -0
- package/packs/event-views-pack.json +33 -0
- package/packs/habit-profile.json +27 -0
- package/packs/hr-pack.json +54 -0
- package/packs/invoice-profile.json +28 -0
- package/packs/knowledge-base-pack.json +56 -0
- package/packs/meeting-profile.json +29 -0
- package/packs/product-profile.json +30 -0
- package/packs/project-management-pack.json +49 -0
- package/packs/recipe-profile.json +29 -0
- package/packs/task-views-pack.json +39 -0
- 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 +99 -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 +135 -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.template.test.ts +25 -19
- package/src/base.yaml +95 -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 +798 -92
- 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 +598 -0
- package/src/catalog-safety.test.ts +198 -0
- package/src/catalog.template-items.test.ts +75 -0
- package/src/catalog.ts +85 -2
- package/src/civic-france.yaml +102 -0
- 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 +322 -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 +1830 -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 +164 -0
- package/src/crm-one-send-door.template.test.ts +65 -0
- package/src/crm.yaml +1456 -181
- package/src/decisions-wave.template.test.ts +186 -0
- package/src/define.ts +130 -17
- package/src/design-to-implementation.template.test.ts +94 -0
- package/src/dist-freshness.test.ts +97 -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 +130 -28
- 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 +57 -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 +65 -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 +83 -0
- package/src/retired-goal-kinds.test.ts +58 -0
- package/src/role-reference-and-step-domain.test.ts +192 -0
- package/src/seed-obligation.test.ts +176 -0
- package/src/send-message-maps.test.ts +227 -0
- package/src/shared-role-ssot.test.ts +42 -1
- 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/task-intents.test.ts +293 -0
- package/src/templates.ts +21639 -21522
- package/src/types.ts +443 -60
- package/src/unipile-publish-post.test.ts +162 -0
- package/src/validate-flow.drift.test.ts +2 -3
- package/src/validate-flow.ts +32 -2
- package/src/validate-onboarding.test.ts +59 -0
- package/src/validate.test.ts +156 -3
- package/src/validate.ts +1384 -7
- package/src/wire-core.ts +231 -0
- package/src/wire.test.ts +159 -0
- package/src/wire.ts +107 -0
- package/src/__fixtures__/report-automation-flow.json +0 -393
- 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/life-os.yaml
CHANGED
|
@@ -13,6 +13,9 @@ meta:
|
|
|
13
13
|
color: "#8B5CF6"
|
|
14
14
|
tags: [pkm, second-brain, knowledge, reading, life-os, notes]
|
|
15
15
|
isPublic: true
|
|
16
|
+
# A LIBRARY: it produces nothing a home counts (homes).
|
|
17
|
+
intent:
|
|
18
|
+
label: Knowledge
|
|
16
19
|
|
|
17
20
|
workspace:
|
|
18
21
|
name: Second Brain — Knowledge OS
|
|
@@ -145,6 +148,12 @@ profiles:
|
|
|
145
148
|
color: "#F59E0B"
|
|
146
149
|
description: Your reading library — track books, progress and insights.
|
|
147
150
|
scope: WORKSPACE
|
|
151
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
152
|
+
presentation:
|
|
153
|
+
family: record
|
|
154
|
+
media:
|
|
155
|
+
source: { property: cover-url }
|
|
156
|
+
kind: image
|
|
148
157
|
properties:
|
|
149
158
|
- slug: title
|
|
150
159
|
label: Title
|
|
@@ -213,6 +222,12 @@ profiles:
|
|
|
213
222
|
# system row and these life-os props land as this workspace's OVERLAY.
|
|
214
223
|
# (Was `scope: WORKSPACE`, which contradicted the pod-wide model.)
|
|
215
224
|
entityScope: pod
|
|
225
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
226
|
+
presentation:
|
|
227
|
+
family: record
|
|
228
|
+
media:
|
|
229
|
+
source: { property: avatar-url }
|
|
230
|
+
kind: image
|
|
216
231
|
properties:
|
|
217
232
|
- slug: name
|
|
218
233
|
label: Name
|
|
@@ -258,41 +273,6 @@ profiles:
|
|
|
258
273
|
valueType: string
|
|
259
274
|
inputType: url
|
|
260
275
|
|
|
261
|
-
- slug: project
|
|
262
|
-
displayName: Project
|
|
263
|
-
icon: FolderOpen
|
|
264
|
-
color: "#F97316"
|
|
265
|
-
description: Bounded efforts with a defined outcome and timeline.
|
|
266
|
-
scope: WORKSPACE
|
|
267
|
-
properties:
|
|
268
|
-
- slug: title
|
|
269
|
-
label: Title
|
|
270
|
-
valueType: string
|
|
271
|
-
inputType: text
|
|
272
|
-
required: true
|
|
273
|
-
- slug: status
|
|
274
|
-
label: Status
|
|
275
|
-
valueType: string
|
|
276
|
-
inputType: select
|
|
277
|
-
enumValues: [idea, planning, active, on-hold, completed, archived]
|
|
278
|
-
- slug: outcome
|
|
279
|
-
label: Outcome
|
|
280
|
-
valueType: string
|
|
281
|
-
inputType: textarea
|
|
282
|
-
- slug: due-date
|
|
283
|
-
label: Due Date
|
|
284
|
-
valueType: date
|
|
285
|
-
inputType: date
|
|
286
|
-
- slug: progress
|
|
287
|
-
label: Progress
|
|
288
|
-
valueType: number
|
|
289
|
-
inputType: number
|
|
290
|
-
constraints: { min: 0, max: 100 }
|
|
291
|
-
- slug: area
|
|
292
|
-
label: Area
|
|
293
|
-
valueType: string
|
|
294
|
-
inputType: text
|
|
295
|
-
|
|
296
276
|
- slug: area
|
|
297
277
|
displayName: Area
|
|
298
278
|
icon: Compass
|
|
@@ -325,6 +305,11 @@ profiles:
|
|
|
325
305
|
color: "#10B981"
|
|
326
306
|
description: Web articles and blog posts worth saving and processing.
|
|
327
307
|
scope: WORKSPACE
|
|
308
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
309
|
+
presentation:
|
|
310
|
+
family: link
|
|
311
|
+
media:
|
|
312
|
+
source: { property: url }
|
|
328
313
|
properties:
|
|
329
314
|
- slug: title
|
|
330
315
|
label: Title
|
|
@@ -362,6 +347,11 @@ profiles:
|
|
|
362
347
|
color: "#3B82F6"
|
|
363
348
|
description: Quick links to valuable resources and pages.
|
|
364
349
|
scope: WORKSPACE
|
|
350
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
351
|
+
presentation:
|
|
352
|
+
family: link
|
|
353
|
+
media:
|
|
354
|
+
source: { property: url }
|
|
365
355
|
properties:
|
|
366
356
|
- slug: title
|
|
367
357
|
label: Title
|
|
@@ -392,6 +382,14 @@ profiles:
|
|
|
392
382
|
color: "#EF4444"
|
|
393
383
|
description: Raw sparks and early-stage thinking.
|
|
394
384
|
scope: WORKSPACE
|
|
385
|
+
# The ONE lifecycle (work model L1): every option's category.
|
|
386
|
+
lifecycle:
|
|
387
|
+
property: status
|
|
388
|
+
options:
|
|
389
|
+
- { key: raw, category: open }
|
|
390
|
+
- { key: exploring, category: active }
|
|
391
|
+
- { key: validated, category: done }
|
|
392
|
+
- { key: shelved, category: paused }
|
|
395
393
|
properties:
|
|
396
394
|
- slug: title
|
|
397
395
|
label: Title
|
|
@@ -416,47 +414,17 @@ profiles:
|
|
|
416
414
|
inputType: number
|
|
417
415
|
constraints: { min: 1, max: 5 }
|
|
418
416
|
|
|
419
|
-
- slug: goal
|
|
420
|
-
displayName: Goal
|
|
421
|
-
icon: Target
|
|
422
|
-
color: "#14B8A6"
|
|
423
|
-
description: Intentions with a target state and measurable progress.
|
|
424
|
-
scope: WORKSPACE
|
|
425
|
-
properties:
|
|
426
|
-
- slug: title
|
|
427
|
-
label: Title
|
|
428
|
-
valueType: string
|
|
429
|
-
inputType: text
|
|
430
|
-
required: true
|
|
431
|
-
- slug: description
|
|
432
|
-
label: Description
|
|
433
|
-
valueType: string
|
|
434
|
-
inputType: textarea
|
|
435
|
-
- slug: status
|
|
436
|
-
label: Status
|
|
437
|
-
valueType: string
|
|
438
|
-
inputType: select
|
|
439
|
-
enumValues: [active, achieved, abandoned]
|
|
440
|
-
- slug: target-date
|
|
441
|
-
label: Target Date
|
|
442
|
-
valueType: date
|
|
443
|
-
inputType: date
|
|
444
|
-
- slug: progress
|
|
445
|
-
label: Progress
|
|
446
|
-
valueType: number
|
|
447
|
-
inputType: number
|
|
448
|
-
constraints: { min: 0, max: 100 }
|
|
449
|
-
- slug: area
|
|
450
|
-
label: Area
|
|
451
|
-
valueType: string
|
|
452
|
-
inputType: text
|
|
453
|
-
|
|
454
417
|
- slug: video
|
|
455
418
|
displayName: Video
|
|
456
419
|
icon: Video
|
|
457
420
|
color: "#8B5CF6"
|
|
458
421
|
description: Video content from YouTube, courses, and other platforms.
|
|
459
422
|
scope: WORKSPACE
|
|
423
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
424
|
+
presentation:
|
|
425
|
+
family: link
|
|
426
|
+
media:
|
|
427
|
+
source: { property: url }
|
|
460
428
|
properties:
|
|
461
429
|
- slug: title
|
|
462
430
|
label: Title
|
|
@@ -490,6 +458,11 @@ profiles:
|
|
|
490
458
|
color: "#EC4899"
|
|
491
459
|
description: Episodes and shows worth listening to or already consumed.
|
|
492
460
|
scope: WORKSPACE
|
|
461
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
462
|
+
presentation:
|
|
463
|
+
family: link
|
|
464
|
+
media:
|
|
465
|
+
source: { property: url }
|
|
493
466
|
properties:
|
|
494
467
|
- slug: title
|
|
495
468
|
label: Title
|
|
@@ -609,6 +582,11 @@ profiles:
|
|
|
609
582
|
color: "#6366F1"
|
|
610
583
|
description: Educational courses you're taking or have completed.
|
|
611
584
|
scope: WORKSPACE
|
|
585
|
+
# How it renders (entity rendering, decision 8): @synap-core/types/presentation.
|
|
586
|
+
presentation:
|
|
587
|
+
family: link
|
|
588
|
+
media:
|
|
589
|
+
source: { property: url }
|
|
612
590
|
properties:
|
|
613
591
|
- slug: title
|
|
614
592
|
label: Title
|
|
@@ -731,6 +709,16 @@ profiles:
|
|
|
731
709
|
inputType: text
|
|
732
710
|
|
|
733
711
|
views:
|
|
712
|
+
# Knowledge is the pod-owned, validated-memory kind. Notes remain the
|
|
713
|
+
# workspace's capture inbox; this view deliberately reuses the system
|
|
714
|
+
# contract instead of recreating a competing knowledge schema here.
|
|
715
|
+
- name: Knowledge
|
|
716
|
+
slug: knowledge
|
|
717
|
+
type: table
|
|
718
|
+
scopeProfileSlug: knowledge
|
|
719
|
+
description: Validated insights and cautions, with their long-form context and evidence kept in the graph.
|
|
720
|
+
config:
|
|
721
|
+
columns: [title, knowledgeForm]
|
|
734
722
|
- name: All Notes
|
|
735
723
|
type: table
|
|
736
724
|
scopeProfileSlug: note
|
|
@@ -769,14 +757,6 @@ views:
|
|
|
769
757
|
- name: People Network
|
|
770
758
|
type: table
|
|
771
759
|
scopeProfileSlug: person
|
|
772
|
-
- name: Active Projects
|
|
773
|
-
type: kanban
|
|
774
|
-
scopeProfileSlug: project
|
|
775
|
-
config:
|
|
776
|
-
groupByField: status
|
|
777
|
-
- name: All Projects
|
|
778
|
-
type: table
|
|
779
|
-
scopeProfileSlug: project
|
|
780
760
|
- name: All Areas
|
|
781
761
|
type: table
|
|
782
762
|
scopeProfileSlug: area
|
|
@@ -799,9 +779,6 @@ views:
|
|
|
799
779
|
scopeProfileSlug: idea
|
|
800
780
|
config:
|
|
801
781
|
groupByField: status
|
|
802
|
-
- name: All Goals
|
|
803
|
-
type: table
|
|
804
|
-
scopeProfileSlug: goal
|
|
805
782
|
- name: Notes Dashboard
|
|
806
783
|
type: bento
|
|
807
784
|
scopeProfileSlug: note
|
|
@@ -1017,68 +994,6 @@ views:
|
|
|
1017
994
|
kind: view
|
|
1018
995
|
viewName: People Network
|
|
1019
996
|
pos: { x: 0, y: 4, w: 12, h: 6 }
|
|
1020
|
-
- name: Projects Dashboard
|
|
1021
|
-
type: bento
|
|
1022
|
-
scopeProfileSlug: project
|
|
1023
|
-
config:
|
|
1024
|
-
blocks:
|
|
1025
|
-
- id: prd-b1
|
|
1026
|
-
kind: widget
|
|
1027
|
-
widgetType: welcome-header
|
|
1028
|
-
pos: { x: 0, y: 0, w: 12, h: 2 }
|
|
1029
|
-
config: { title: Projects, subtitle: Your active initiatives }
|
|
1030
|
-
- id: prd-b2
|
|
1031
|
-
kind: widget
|
|
1032
|
-
widgetType: entity-count
|
|
1033
|
-
pos: { x: 0, y: 2, w: 3, h: 2 }
|
|
1034
|
-
config:
|
|
1035
|
-
{
|
|
1036
|
-
profileSlug: project,
|
|
1037
|
-
label: Active,
|
|
1038
|
-
icon: Play,
|
|
1039
|
-
filter: { status: active },
|
|
1040
|
-
color: green,
|
|
1041
|
-
}
|
|
1042
|
-
- id: prd-b3
|
|
1043
|
-
kind: widget
|
|
1044
|
-
widgetType: entity-count
|
|
1045
|
-
pos: { x: 3, y: 2, w: 3, h: 2 }
|
|
1046
|
-
config:
|
|
1047
|
-
{
|
|
1048
|
-
profileSlug: project,
|
|
1049
|
-
label: Planning,
|
|
1050
|
-
icon: Map,
|
|
1051
|
-
filter: { status: planning },
|
|
1052
|
-
color: blue,
|
|
1053
|
-
}
|
|
1054
|
-
- id: prd-b4
|
|
1055
|
-
kind: widget
|
|
1056
|
-
widgetType: entity-count
|
|
1057
|
-
pos: { x: 6, y: 2, w: 3, h: 2 }
|
|
1058
|
-
config:
|
|
1059
|
-
{
|
|
1060
|
-
profileSlug: project,
|
|
1061
|
-
label: On Hold,
|
|
1062
|
-
icon: PauseCircle,
|
|
1063
|
-
filter: { status: on-hold },
|
|
1064
|
-
color: amber,
|
|
1065
|
-
}
|
|
1066
|
-
- id: prd-b5
|
|
1067
|
-
kind: widget
|
|
1068
|
-
widgetType: entity-count
|
|
1069
|
-
pos: { x: 9, y: 2, w: 3, h: 2 }
|
|
1070
|
-
config:
|
|
1071
|
-
{
|
|
1072
|
-
profileSlug: project,
|
|
1073
|
-
label: Completed,
|
|
1074
|
-
icon: CheckCircle,
|
|
1075
|
-
filter: { status: completed },
|
|
1076
|
-
color: purple,
|
|
1077
|
-
}
|
|
1078
|
-
- id: prd-b6
|
|
1079
|
-
kind: view
|
|
1080
|
-
viewName: Active Projects
|
|
1081
|
-
pos: { x: 0, y: 4, w: 12, h: 6 }
|
|
1082
997
|
- name: Quotes Dashboard
|
|
1083
998
|
type: bento
|
|
1084
999
|
scopeProfileSlug: quote
|
|
@@ -1136,12 +1051,6 @@ views:
|
|
|
1136
1051
|
icon: Compass,
|
|
1137
1052
|
filter: { status: active },
|
|
1138
1053
|
}
|
|
1139
|
-
- id: ad-b3
|
|
1140
|
-
kind: widget
|
|
1141
|
-
widgetType: entity-count
|
|
1142
|
-
pos: { x: 6, y: 2, w: 6, h: 2 }
|
|
1143
|
-
config:
|
|
1144
|
-
{ profileSlug: project, label: Total Projects, icon: FolderOpen }
|
|
1145
1054
|
- id: ad-b4
|
|
1146
1055
|
kind: view
|
|
1147
1056
|
viewName: All Areas
|
|
@@ -1160,6 +1069,10 @@ layout:
|
|
|
1160
1069
|
appId: dashboard
|
|
1161
1070
|
label: Brain Home
|
|
1162
1071
|
icon: Home
|
|
1072
|
+
- kind: profile
|
|
1073
|
+
profileSlug: knowledge
|
|
1074
|
+
label: Knowledge
|
|
1075
|
+
icon: Brain
|
|
1163
1076
|
- kind: profile
|
|
1164
1077
|
profileSlug: note
|
|
1165
1078
|
label: Notes
|
|
@@ -1192,10 +1105,6 @@ layout:
|
|
|
1192
1105
|
profileSlug: person
|
|
1193
1106
|
label: People
|
|
1194
1107
|
icon: Users
|
|
1195
|
-
- kind: profile
|
|
1196
|
-
profileSlug: project
|
|
1197
|
-
label: Projects
|
|
1198
|
-
icon: FolderOpen
|
|
1199
1108
|
- kind: profile
|
|
1200
1109
|
profileSlug: area
|
|
1201
1110
|
label: Areas
|
|
@@ -1218,10 +1127,6 @@ entityLinks:
|
|
|
1218
1127
|
targetProfileSlug: book
|
|
1219
1128
|
type: references
|
|
1220
1129
|
label: References
|
|
1221
|
-
- sourceProfileSlug: note
|
|
1222
|
-
targetProfileSlug: project
|
|
1223
|
-
type: feeds-into
|
|
1224
|
-
label: Feeds into
|
|
1225
1130
|
- sourceProfileSlug: highlight
|
|
1226
1131
|
targetProfileSlug: book
|
|
1227
1132
|
type: from
|
|
@@ -1238,18 +1143,6 @@ entityLinks:
|
|
|
1238
1143
|
targetProfileSlug: person
|
|
1239
1144
|
type: written-by
|
|
1240
1145
|
label: Written by
|
|
1241
|
-
- sourceProfileSlug: idea
|
|
1242
|
-
targetProfileSlug: project
|
|
1243
|
-
type: feeds-into
|
|
1244
|
-
label: Feeds into
|
|
1245
|
-
- sourceProfileSlug: project
|
|
1246
|
-
targetProfileSlug: area
|
|
1247
|
-
type: belongs-to
|
|
1248
|
-
label: Belongs to
|
|
1249
|
-
- sourceProfileSlug: goal
|
|
1250
|
-
targetProfileSlug: area
|
|
1251
|
-
type: in-area
|
|
1252
|
-
label: In area
|
|
1253
1146
|
- sourceProfileSlug: concept
|
|
1254
1147
|
targetProfileSlug: concept
|
|
1255
1148
|
type: related-to
|
|
@@ -1304,7 +1197,6 @@ bento:
|
|
|
1304
1197
|
- { label: Add Book, icon: BookOpen, profileSlug: book }
|
|
1305
1198
|
- { label: Capture Idea, icon: Zap, profileSlug: idea }
|
|
1306
1199
|
- { label: Concepts, icon: Lightbulb, profileSlug: concept }
|
|
1307
|
-
- { label: Projects, icon: FolderOpen, profileSlug: project }
|
|
1308
1200
|
- { label: People, icon: Users, profileSlug: person }
|
|
1309
1201
|
- kind: widget
|
|
1310
1202
|
widgetType: calendar
|
|
@@ -1423,28 +1315,6 @@ profileEntityBentoTemplates:
|
|
|
1423
1315
|
widgetType: entity-list
|
|
1424
1316
|
pos: { x: 6, y: 3, w: 6, h: 4 }
|
|
1425
1317
|
config: { profileSlug: article, title: Articles by, limit: 8 }
|
|
1426
|
-
project:
|
|
1427
|
-
blocks:
|
|
1428
|
-
- id: project-eb-b1
|
|
1429
|
-
kind: widget
|
|
1430
|
-
widgetType: entity-spotlight
|
|
1431
|
-
pos: { x: 0, y: 0, w: 8, h: 3 }
|
|
1432
|
-
config: { seed: pinned, layout: detail }
|
|
1433
|
-
- id: project-eb-b2
|
|
1434
|
-
kind: widget
|
|
1435
|
-
widgetType: entity-count
|
|
1436
|
-
pos: { x: 8, y: 0, w: 4, h: 3 }
|
|
1437
|
-
config: { profileSlug: idea, label: Ideas, icon: Zap }
|
|
1438
|
-
- id: project-eb-b3
|
|
1439
|
-
kind: widget
|
|
1440
|
-
widgetType: entity-list
|
|
1441
|
-
pos: { x: 0, y: 3, w: 6, h: 4 }
|
|
1442
|
-
config: { profileSlug: note, title: Project Notes, limit: 8 }
|
|
1443
|
-
- id: project-eb-b4
|
|
1444
|
-
kind: widget
|
|
1445
|
-
widgetType: entity-list
|
|
1446
|
-
pos: { x: 6, y: 3, w: 6, h: 4 }
|
|
1447
|
-
config: { profileSlug: idea, title: Ideas, limit: 8 }
|
|
1448
1318
|
area:
|
|
1449
1319
|
blocks:
|
|
1450
1320
|
- id: area-eb-b1
|
|
@@ -1452,50 +1322,11 @@ profileEntityBentoTemplates:
|
|
|
1452
1322
|
widgetType: entity-spotlight
|
|
1453
1323
|
pos: { x: 0, y: 0, w: 8, h: 3 }
|
|
1454
1324
|
config: { seed: pinned, layout: detail }
|
|
1455
|
-
- id: area-eb-b2
|
|
1456
|
-
kind: widget
|
|
1457
|
-
widgetType: entity-count
|
|
1458
|
-
pos: { x: 8, y: 0, w: 4, h: 3 }
|
|
1459
|
-
config:
|
|
1460
|
-
{
|
|
1461
|
-
profileSlug: project,
|
|
1462
|
-
label: Projects,
|
|
1463
|
-
icon: FolderOpen,
|
|
1464
|
-
color: green,
|
|
1465
|
-
}
|
|
1466
|
-
- id: area-eb-b3
|
|
1467
|
-
kind: widget
|
|
1468
|
-
widgetType: entity-list
|
|
1469
|
-
pos: { x: 0, y: 3, w: 12, h: 4 }
|
|
1470
|
-
config: { profileSlug: project, title: Projects, limit: 10 }
|
|
1471
|
-
goal:
|
|
1472
|
-
blocks:
|
|
1473
|
-
- id: goal-eb-b1
|
|
1474
|
-
kind: widget
|
|
1475
|
-
widgetType: entity-spotlight
|
|
1476
|
-
pos: { x: 0, y: 0, w: 8, h: 3 }
|
|
1477
|
-
config: { seed: pinned, layout: detail }
|
|
1478
|
-
- id: goal-eb-b2
|
|
1479
|
-
kind: widget
|
|
1480
|
-
widgetType: metrics-summary
|
|
1481
|
-
pos: { x: 8, y: 0, w: 4, h: 3 }
|
|
1482
|
-
config:
|
|
1483
|
-
{
|
|
1484
|
-
profileSlug: project,
|
|
1485
|
-
property: progress,
|
|
1486
|
-
aggregation: average,
|
|
1487
|
-
title: Avg Project Progress,
|
|
1488
|
-
}
|
|
1489
|
-
- id: goal-eb-b3
|
|
1490
|
-
kind: widget
|
|
1491
|
-
widgetType: entity-list
|
|
1492
|
-
pos: { x: 0, y: 3, w: 12, h: 4 }
|
|
1493
|
-
config: { profileSlug: project, title: Related Projects, limit: 8 }
|
|
1494
1325
|
|
|
1495
1326
|
# Per-workspace adaptive onboarding context (from synap-backend life-os.package.json)
|
|
1496
1327
|
onboarding:
|
|
1497
1328
|
goal: Capture the shape of the user's life — their areas of focus, current goals, active projects, key people, and what they're reading or learning — so the second brain starts grounded in who they actually are.
|
|
1498
|
-
framing: Act as a thoughtful personal-knowledge coach. Gently tease out the domains they care about, what they're working toward, what's in motion, who matters to them, and what they're consuming. Translate that into areas,
|
|
1329
|
+
framing: Act as a thoughtful personal-knowledge coach. Gently tease out the domains they care about, what they're working toward, what's in motion, who matters to them, and what they're consuming. Translate that into areas, projects, people, and books. Goals are the pod's own goals (tracks), not an entity kind in this space; start each as a track (a goal) and file its notes into its project. Projects are the pod's own projects, not an entity kind; create each through the project door and file its notes into it.
|
|
1499
1330
|
expertise:
|
|
1500
1331
|
starters:
|
|
1501
1332
|
- >
|
|
@@ -1536,22 +1367,16 @@ onboarding:
|
|
|
1536
1367
|
a next action, and a review habit named so the system gets revisited, not just fed.
|
|
1537
1368
|
collect:
|
|
1538
1369
|
- profileSlug: area
|
|
1370
|
+
min: 1
|
|
1539
1371
|
what: The ongoing areas of life / responsibility they want to keep standards in
|
|
1540
1372
|
cardinality: few
|
|
1541
1373
|
keyFields: [title, description, standard]
|
|
1542
|
-
- profileSlug: goal
|
|
1543
|
-
what: The goals they're currently working toward
|
|
1544
|
-
cardinality: few
|
|
1545
|
-
keyFields: [title, target-date, area, progress]
|
|
1546
|
-
- profileSlug: project
|
|
1547
|
-
what: The active projects in motion (the concrete efforts that advance their goals)
|
|
1548
|
-
cardinality: few
|
|
1549
|
-
keyFields: [title, status]
|
|
1550
1374
|
- profileSlug: person
|
|
1551
1375
|
what: The key people in their world
|
|
1552
1376
|
cardinality: several
|
|
1553
1377
|
keyFields: [name, relationship, company]
|
|
1554
1378
|
- profileSlug: book
|
|
1379
|
+
min: 1
|
|
1555
1380
|
what: What they're currently reading or learning from
|
|
1556
1381
|
cardinality: few
|
|
1557
1382
|
keyFields: [title, author, status]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle coverage — kinds with a lifecycle should have a process that moves it.
|
|
3
|
+
*
|
|
4
|
+
* A kind with a lifecycle select (`post-status`, `deal-stage`, …) is a process
|
|
5
|
+
* waiting to be declared: the engine can bind a playbook's stages to it
|
|
6
|
+
* (`subjectProfile.statusProperty` + `stages[].subjectStatus`), but only if a
|
|
7
|
+
* playbook binds the kind at all. This file holds two guards.
|
|
8
|
+
*
|
|
9
|
+
* (1) RATCHET. Count the kinds across the WHOLE corpus that have a lifecycle and
|
|
10
|
+
* that NO playbook binds through `subjectProfile`. It may only go DOWN:
|
|
11
|
+
* `count <= BASELINE`. Lower BASELINE when you bind a kind; never raise it to
|
|
12
|
+
* bank a new unbound lifecycle kind — bind it, or don't give it a lifecycle.
|
|
13
|
+
*
|
|
14
|
+
* "Has a lifecycle" = a `select` property whose slug contains "status" or
|
|
15
|
+
* "stage", CASE-INSENSITIVE. EXCLUDED: agent/runtime machine state, which
|
|
16
|
+
* the system writes and no person or process moves through —
|
|
17
|
+
* `agent_status`, `runStatus`, `lastRunStatus`, `run_status`, `job-status`
|
|
18
|
+
* (RUNTIME_STATUS below). Kind identity is the profile slug, deduplicated
|
|
19
|
+
* across templates (a shared kind re-declared in two templates counts once).
|
|
20
|
+
*
|
|
21
|
+
* (2) COVERAGE. For every playbook whose stages bind the lifecycle (it declares
|
|
22
|
+
* `subjectProfile.statusProperty` AND at least one stage `subjectStatus`),
|
|
23
|
+
* every enum value of that property must be some stage's `subjectStatus` or
|
|
24
|
+
* listed in `humanOnlyStatuses`. A value in neither is a state the process
|
|
25
|
+
* silently cannot reach or leave.
|
|
26
|
+
*
|
|
27
|
+
* NOT covered: a playbook that declares `statusProperty` only to READ the
|
|
28
|
+
* lifecycle (an activator, e.g. Content OS "Repurpose" fires on Published
|
|
29
|
+
* and creates NEW posts) and binds no stage. It owns no status, so asking it
|
|
30
|
+
* to cover the enum would force it to list every value as human-only.
|
|
31
|
+
*
|
|
32
|
+
* The functions + BASELINE live in scripts/catalog-lib.mjs (validateCatalog
|
|
33
|
+
* enforces them at publish). Both scans derive their set by globbing `src/*.yaml` (readYamlTemplates);
|
|
34
|
+
* nothing is hand-listed. Negative controls (run 2026-10-08): baseline 94 →
|
|
35
|
+
* red "expected 95 to be less than or equal to 94"; removing "Archived" from
|
|
36
|
+
* Produce Content's humanOnlyStatuses → red, naming `post-status = Archived`.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import { describe, expect, it } from "vitest";
|
|
40
|
+
import { readYamlTemplates } from "./generate.mjs";
|
|
41
|
+
import type { WorkspaceYaml } from "./types.js";
|
|
42
|
+
// The rule lives in the ONE catalog lib (validateCatalog runs it on every
|
|
43
|
+
// publish); this file pins it against the real corpus.
|
|
44
|
+
import {
|
|
45
|
+
LIFECYCLE_BASELINE as BASELINE,
|
|
46
|
+
LIFECYCLE_PATTERNS,
|
|
47
|
+
boundKinds,
|
|
48
|
+
lifecycleKinds,
|
|
49
|
+
unboundLifecycleKinds,
|
|
50
|
+
uncoveredStatuses,
|
|
51
|
+
} from "../scripts/catalog-lib.mjs";
|
|
52
|
+
|
|
53
|
+
const { RUNTIME_STATUS, LIFECYCLE } = LIFECYCLE_PATTERNS;
|
|
54
|
+
|
|
55
|
+
const corpus = readYamlTemplates().map((t) => t.data as WorkspaceYaml);
|
|
56
|
+
|
|
57
|
+
describe("lifecycle coverage — ratchet", () => {
|
|
58
|
+
it("non-vacuity: the scan sees the corpus and a literal lifecycle kind", () => {
|
|
59
|
+
expect(corpus.length).toBeGreaterThanOrEqual(25);
|
|
60
|
+
const kinds = lifecycleKinds(corpus);
|
|
61
|
+
expect(kinds.size).toBeGreaterThanOrEqual(80);
|
|
62
|
+
expect(kinds.get("post")?.has("post-status")).toBe(true);
|
|
63
|
+
// Case-insensitive: a camelCase lifecycle field is seen.
|
|
64
|
+
expect(LIFECYCLE.test("dealStage")).toBe(true);
|
|
65
|
+
// The runtime exclusion sees what it excludes, and only that.
|
|
66
|
+
for (const s of ["agent_status", "runStatus", "lastRunStatus", "run_status", "job-status"])
|
|
67
|
+
expect(RUNTIME_STATUS.test(s)).toBe(true);
|
|
68
|
+
expect(RUNTIME_STATUS.test("post-status")).toBe(false);
|
|
69
|
+
expect(boundKinds(corpus).has("post")).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it(`unbound lifecycle kinds never grow past the baseline (${BASELINE})`, () => {
|
|
73
|
+
const unbound = unboundLifecycleKinds(corpus);
|
|
74
|
+
expect(unbound.length, unbound.join(", ")).toBeLessThanOrEqual(BASELINE);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("lifecycle coverage — every status of a stage-bound lifecycle is owned", () => {
|
|
79
|
+
it("non-vacuity: at least two playbooks bind stages to a lifecycle", () => {
|
|
80
|
+
const binders = corpus.flatMap((t) =>
|
|
81
|
+
(t.playbooks ?? []).filter(
|
|
82
|
+
(pb) => pb.subjectProfile?.statusProperty && (pb.stages ?? []).some((s) => s.subjectStatus)
|
|
83
|
+
)
|
|
84
|
+
);
|
|
85
|
+
expect(binders.length).toBeGreaterThanOrEqual(2);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("self-check: an un-owned status is reported", () => {
|
|
89
|
+
const clone = structuredClone(corpus);
|
|
90
|
+
const produce = clone
|
|
91
|
+
.find((t) => t.meta.slug === "content-os")!
|
|
92
|
+
.playbooks!.find((p) => p.name === "Produce Content")!;
|
|
93
|
+
produce.humanOnlyStatuses = ["Idea"];
|
|
94
|
+
expect(uncoveredStatuses(clone)).toContain("content-os › Produce Content: post-status = Archived");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("every enum value is a stage's subjectStatus or a humanOnlyStatus", () => {
|
|
98
|
+
expect(uncoveredStatuses(corpus)).toEqual([]);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// ONE LIFECYCLE PER KIND OR ROLE (work model, founder rule 2026-10-11). A
|
|
103
|
+
// second lifecycle select on the same kind is two truths about where the thing
|
|
104
|
+
// stands (deal once carried `dealStage` AND `commercialStage`; the lead role
|
|
105
|
+
// `leadStage` AND an overlay `lifecycleStage`). RATCHET on the EXCESS — the sum
|
|
106
|
+
// over kinds of (lifecycle-named selects − 1) — so re-adding a second stage to a
|
|
107
|
+
// kind that is already counted still turns this red. It counts by NAME, so side
|
|
108
|
+
// statuses (`handoffStatus`, `commissionStatus`) are counted too: that is the
|
|
109
|
+
// limit of a name scan, and why this is a ratchet, not a zero assertion.
|
|
110
|
+
// Lower EXCESS_BASELINE when you fold one; never raise it.
|
|
111
|
+
const EXCESS_BASELINE = 9;
|
|
112
|
+
describe("one lifecycle per kind or role — ratchet", () => {
|
|
113
|
+
it(`excess lifecycle-named selects never grow past ${EXCESS_BASELINE}`, () => {
|
|
114
|
+
const kinds = lifecycleKinds(corpus);
|
|
115
|
+
const multi = [...kinds].filter(([, set]) => set.size > 1);
|
|
116
|
+
const excess = multi.reduce((n, [, set]) => n + set.size - 1, 0);
|
|
117
|
+
expect(kinds.get("deal")?.has("commercialStage")).toBe(true); // non-vacuity
|
|
118
|
+
expect(kinds.get("deal")?.has("dealStage"), "deal's retired dealStage is back").toBe(false);
|
|
119
|
+
expect(kinds.get("lead")?.has("lifecycleStage"), "lead's retired lifecycleStage is back").toBe(false);
|
|
120
|
+
expect(excess, multi.map(([k, s]) => `${k}: ${[...s].join(",")}`).join("; ")).toBeLessThanOrEqual(
|
|
121
|
+
EXCESS_BASELINE
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
});
|