@synap-core/workspace-templates 0.11.0 → 0.12.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/dist/index.d.ts +15 -0
- package/dist/index.js +802 -4
- package/dist/index.js.map +1 -1
- package/package.json +16 -25
- package/src/base.template.test.ts +25 -19
- package/src/base.yaml +10 -0
- package/src/builder.yaml +19 -1
- package/src/business-model.yaml +351 -0
- package/src/catalog.ts +19 -0
- package/src/civic-france.yaml +102 -0
- package/src/dist-freshness.test.ts +97 -0
- package/src/foundation.yaml +62 -0
- package/src/grants.yaml +17 -6
- package/src/life-os.yaml +14 -0
- package/src/seed-obligation.test.ts +181 -0
- package/src/shared-role-ssot.test.ts +4 -1
- package/src/templates.ts +765 -3
- package/src/validate-flow.ts +11 -1
- package/src/validate.test.ts +86 -0
- package/src/validate.ts +49 -0
- package/src/__fixtures__/report-automation-flow.json +0 -393
package/dist/index.js
CHANGED
|
@@ -3213,7 +3213,9 @@ var DATA = {
|
|
|
3213
3213
|
"maxTokens": "2000"
|
|
3214
3214
|
},
|
|
3215
3215
|
"errorHandling": {
|
|
3216
|
-
"continueOnError": true
|
|
3216
|
+
"continueOnError": true,
|
|
3217
|
+
"maxRetries": 1,
|
|
3218
|
+
"retryDelay": 5e3
|
|
3217
3219
|
}
|
|
3218
3220
|
}
|
|
3219
3221
|
},
|
|
@@ -3234,7 +3236,9 @@ var DATA = {
|
|
|
3234
3236
|
"maxTokens": "2000"
|
|
3235
3237
|
},
|
|
3236
3238
|
"errorHandling": {
|
|
3237
|
-
"continueOnError": true
|
|
3239
|
+
"continueOnError": true,
|
|
3240
|
+
"maxRetries": 1,
|
|
3241
|
+
"retryDelay": 5e3
|
|
3238
3242
|
}
|
|
3239
3243
|
}
|
|
3240
3244
|
},
|
|
@@ -3411,6 +3415,10 @@ Be CONCISE \u2014 your entire output must fit in 2000 tokens. Emit ONLY the mark
|
|
|
3411
3415
|
document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
3412
3416
|
"prompt": "STEER:\n- Prompt: {{trigger.payload.prompt}}\n- Focus: {{trigger.payload.focus}}\n- Project lens id: {{trigger.payload.projectId}}\n\nReport generated at: {{steps.now.output.result}}\n\nANALYZE ROUND MATERIAL:\n{{steps.analyze.output}}\n\nRELATE ROUND MATERIAL:\n{{steps.relate.output}}",
|
|
3413
3417
|
"maxTokens": "2000"
|
|
3418
|
+
},
|
|
3419
|
+
"errorHandling": {
|
|
3420
|
+
"maxRetries": 1,
|
|
3421
|
+
"retryDelay": 5e3
|
|
3414
3422
|
}
|
|
3415
3423
|
}
|
|
3416
3424
|
},
|
|
@@ -3429,6 +3437,10 @@ document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
|
3429
3437
|
"system": 'Write ONE plain sentence, under 200 characters, stating what this report found.\nNo markdown, no directives, no quotes, no leading label. Just the sentence.\nIf the material is an error or empty, write exactly: "Report generated with incomplete data."',
|
|
3430
3438
|
"prompt": "Material to summarize (may be an error object if the round failed):\n{{steps.analyze.output}}",
|
|
3431
3439
|
"maxTokens": "500"
|
|
3440
|
+
},
|
|
3441
|
+
"errorHandling": {
|
|
3442
|
+
"maxRetries": 1,
|
|
3443
|
+
"retryDelay": 5e3
|
|
3432
3444
|
}
|
|
3433
3445
|
}
|
|
3434
3446
|
},
|
|
@@ -5324,7 +5336,8 @@ document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
|
5324
5336
|
"builder.apps",
|
|
5325
5337
|
"builder.deployments",
|
|
5326
5338
|
"builder.agents",
|
|
5327
|
-
"builder.packages"
|
|
5339
|
+
"builder.packages",
|
|
5340
|
+
"devplane.workspace"
|
|
5328
5341
|
]
|
|
5329
5342
|
},
|
|
5330
5343
|
"profiles": [
|
|
@@ -8876,6 +8889,640 @@ document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
|
8876
8889
|
}
|
|
8877
8890
|
]
|
|
8878
8891
|
},
|
|
8892
|
+
"business-model": {
|
|
8893
|
+
"meta": {
|
|
8894
|
+
"slug": "business-model",
|
|
8895
|
+
"domain": "strategy",
|
|
8896
|
+
"name": "Business Model",
|
|
8897
|
+
"description": "Interrogate a venture as a model that rests on things \u2014 components supported by evidence, bound by real conventions, and quantified by projections whose assumptions stay visible.",
|
|
8898
|
+
"icon": "layout-grid",
|
|
8899
|
+
"color": "#0EA5E9",
|
|
8900
|
+
"tags": [
|
|
8901
|
+
"strategy",
|
|
8902
|
+
"business-model",
|
|
8903
|
+
"grp",
|
|
8904
|
+
"ibis",
|
|
8905
|
+
"viability"
|
|
8906
|
+
],
|
|
8907
|
+
"isPublic": true
|
|
8908
|
+
},
|
|
8909
|
+
"workspace": {
|
|
8910
|
+
"name": "Foundation",
|
|
8911
|
+
"description": "Adds business-model interrogation to the strategic substrate \u2014 what the model rests on, which conventions bind it, and which numbers assume what.",
|
|
8912
|
+
"subtype": "foundation"
|
|
8913
|
+
},
|
|
8914
|
+
"dependencies": [
|
|
8915
|
+
{
|
|
8916
|
+
"slug": "foundation",
|
|
8917
|
+
"relation": "compose",
|
|
8918
|
+
"reason": "The model's components ARE the foundation vocabulary \u2014 mission, audience, pain-point, positioning, offer, and the client/partner/porteur/funder roles. This pack interrogates them; it does not restate them."
|
|
8919
|
+
}
|
|
8920
|
+
],
|
|
8921
|
+
"profiles": [
|
|
8922
|
+
{
|
|
8923
|
+
"slug": "question",
|
|
8924
|
+
"displayName": "Question",
|
|
8925
|
+
"icon": "help-circle",
|
|
8926
|
+
"profileKind": "kind",
|
|
8927
|
+
"properties": [
|
|
8928
|
+
{
|
|
8929
|
+
"slug": "questionStatus",
|
|
8930
|
+
"label": "Status",
|
|
8931
|
+
"valueType": "string",
|
|
8932
|
+
"inputType": "select",
|
|
8933
|
+
"enumValues": [
|
|
8934
|
+
"open",
|
|
8935
|
+
"exploring",
|
|
8936
|
+
"answered",
|
|
8937
|
+
"abandoned"
|
|
8938
|
+
]
|
|
8939
|
+
}
|
|
8940
|
+
]
|
|
8941
|
+
},
|
|
8942
|
+
{
|
|
8943
|
+
"slug": "decision",
|
|
8944
|
+
"displayName": "Decision",
|
|
8945
|
+
"icon": "gavel",
|
|
8946
|
+
"profileKind": "kind",
|
|
8947
|
+
"properties": [
|
|
8948
|
+
{
|
|
8949
|
+
"slug": "decisionStatus",
|
|
8950
|
+
"label": "Status",
|
|
8951
|
+
"valueType": "string",
|
|
8952
|
+
"inputType": "select",
|
|
8953
|
+
"enumValues": [
|
|
8954
|
+
"proposed",
|
|
8955
|
+
"accepted",
|
|
8956
|
+
"superseded",
|
|
8957
|
+
"rejected"
|
|
8958
|
+
]
|
|
8959
|
+
}
|
|
8960
|
+
]
|
|
8961
|
+
},
|
|
8962
|
+
{
|
|
8963
|
+
"slug": "convention",
|
|
8964
|
+
"displayName": "Convention",
|
|
8965
|
+
"icon": "scale",
|
|
8966
|
+
"color": "rose",
|
|
8967
|
+
"description": "A binding rule the model must satisfy and did not choose \u2014 an eligibility threshold, a professional duty, a contractual floor, a platform policy. Distinct from a decision (nobody decided it) and from a finding (it constrains rather than informs).",
|
|
8968
|
+
"profileKind": "kind",
|
|
8969
|
+
"properties": [
|
|
8970
|
+
{
|
|
8971
|
+
"slug": "rule",
|
|
8972
|
+
"label": "The Rule",
|
|
8973
|
+
"valueType": "string",
|
|
8974
|
+
"inputType": "textarea",
|
|
8975
|
+
"description": "State the constraint in the terms the issuer uses, not in a paraphrase. Paraphrase is where eligibility collisions hide."
|
|
8976
|
+
},
|
|
8977
|
+
{
|
|
8978
|
+
"slug": "issuer",
|
|
8979
|
+
"label": "Issued By",
|
|
8980
|
+
"valueType": "string",
|
|
8981
|
+
"inputType": "text",
|
|
8982
|
+
"description": "Who imposes it \u2014 a regulator, a funder, an ordre professionnel, a platform, a counterparty."
|
|
8983
|
+
},
|
|
8984
|
+
{
|
|
8985
|
+
"slug": "conventionType",
|
|
8986
|
+
"label": "Type",
|
|
8987
|
+
"valueType": "string",
|
|
8988
|
+
"inputType": "select",
|
|
8989
|
+
"enumValues": [
|
|
8990
|
+
"regulatory",
|
|
8991
|
+
"deontological",
|
|
8992
|
+
"eligibility",
|
|
8993
|
+
"contractual",
|
|
8994
|
+
"platform",
|
|
8995
|
+
"fiscal",
|
|
8996
|
+
"other"
|
|
8997
|
+
]
|
|
8998
|
+
},
|
|
8999
|
+
{
|
|
9000
|
+
"slug": "bindingStatus",
|
|
9001
|
+
"label": "Binding Status",
|
|
9002
|
+
"valueType": "string",
|
|
9003
|
+
"inputType": "select",
|
|
9004
|
+
"enumValues": [
|
|
9005
|
+
"verified",
|
|
9006
|
+
"assumed",
|
|
9007
|
+
"contested",
|
|
9008
|
+
"expired"
|
|
9009
|
+
],
|
|
9010
|
+
"description": "`assumed` is the dangerous default \u2014 it means nobody has read the source text yet."
|
|
9011
|
+
},
|
|
9012
|
+
{
|
|
9013
|
+
"slug": "sourceReference",
|
|
9014
|
+
"label": "Source Reference",
|
|
9015
|
+
"valueType": "string",
|
|
9016
|
+
"inputType": "text",
|
|
9017
|
+
"description": "The cahier des charges, article, or guide this comes from. A convention with no reference is an assumption wearing a rule's clothes."
|
|
9018
|
+
},
|
|
9019
|
+
{
|
|
9020
|
+
"slug": "expiresAt",
|
|
9021
|
+
"label": "Expires / Review By",
|
|
9022
|
+
"valueType": "date",
|
|
9023
|
+
"inputType": "date"
|
|
9024
|
+
},
|
|
9025
|
+
{
|
|
9026
|
+
"slug": "consequenceIfBreached",
|
|
9027
|
+
"label": "Consequence If Breached",
|
|
9028
|
+
"valueType": "string",
|
|
9029
|
+
"inputType": "textarea"
|
|
9030
|
+
}
|
|
9031
|
+
]
|
|
9032
|
+
},
|
|
9033
|
+
{
|
|
9034
|
+
"slug": "projection",
|
|
9035
|
+
"displayName": "Projection",
|
|
9036
|
+
"icon": "trending-up",
|
|
9037
|
+
"color": "violet",
|
|
9038
|
+
"description": "A quantified scenario with its assumptions attached. The number is never the artifact \u2014 the assumptions are, because that is the only part anyone can argue with.",
|
|
9039
|
+
"profileKind": "kind",
|
|
9040
|
+
"properties": [
|
|
9041
|
+
{
|
|
9042
|
+
"slug": "scenario",
|
|
9043
|
+
"label": "Scenario",
|
|
9044
|
+
"valueType": "string",
|
|
9045
|
+
"inputType": "select",
|
|
9046
|
+
"enumValues": [
|
|
9047
|
+
"pessimistic",
|
|
9048
|
+
"base",
|
|
9049
|
+
"optimistic"
|
|
9050
|
+
]
|
|
9051
|
+
},
|
|
9052
|
+
{
|
|
9053
|
+
"slug": "horizon",
|
|
9054
|
+
"label": "Horizon",
|
|
9055
|
+
"valueType": "string",
|
|
9056
|
+
"inputType": "select",
|
|
9057
|
+
"enumValues": [
|
|
9058
|
+
"month",
|
|
9059
|
+
"quarter",
|
|
9060
|
+
"year",
|
|
9061
|
+
"three-year"
|
|
9062
|
+
]
|
|
9063
|
+
},
|
|
9064
|
+
{
|
|
9065
|
+
"slug": "assumptions",
|
|
9066
|
+
"label": "Assumptions",
|
|
9067
|
+
"valueType": "string",
|
|
9068
|
+
"inputType": "textarea",
|
|
9069
|
+
"description": "Every input this number needs to be true. When one changes, whatever rests on this projection goes stale."
|
|
9070
|
+
},
|
|
9071
|
+
{
|
|
9072
|
+
"slug": "revenueEstimate",
|
|
9073
|
+
"label": "Revenue Estimate",
|
|
9074
|
+
"valueType": "number",
|
|
9075
|
+
"inputType": "number"
|
|
9076
|
+
},
|
|
9077
|
+
{
|
|
9078
|
+
"slug": "costEstimate",
|
|
9079
|
+
"label": "Cost Estimate",
|
|
9080
|
+
"valueType": "number",
|
|
9081
|
+
"inputType": "number"
|
|
9082
|
+
},
|
|
9083
|
+
{
|
|
9084
|
+
"slug": "breakEvenUnits",
|
|
9085
|
+
"label": "Break-Even Units",
|
|
9086
|
+
"valueType": "number",
|
|
9087
|
+
"inputType": "number"
|
|
9088
|
+
},
|
|
9089
|
+
{
|
|
9090
|
+
"slug": "confidence",
|
|
9091
|
+
"label": "Confidence",
|
|
9092
|
+
"valueType": "string",
|
|
9093
|
+
"inputType": "select",
|
|
9094
|
+
"enumValues": [
|
|
9095
|
+
"low",
|
|
9096
|
+
"medium",
|
|
9097
|
+
"high"
|
|
9098
|
+
]
|
|
9099
|
+
}
|
|
9100
|
+
]
|
|
9101
|
+
}
|
|
9102
|
+
],
|
|
9103
|
+
"relationDefs": [
|
|
9104
|
+
{
|
|
9105
|
+
"slug": "rests_on",
|
|
9106
|
+
"displayName": "Rests On",
|
|
9107
|
+
"description": "The source depends on the target for its validity \u2014 not for its scheduling. Cycles are LEGAL and meaningful here: a business model is mutually supporting by nature, and forcing it into an acyclic dependency graph destroys the information. When the target changes, everything resting on it is stale until re-checked.",
|
|
9108
|
+
"isDirectional": true,
|
|
9109
|
+
"uiHints": {
|
|
9110
|
+
"category": "reference",
|
|
9111
|
+
"inverseLabel": "Supports"
|
|
9112
|
+
}
|
|
9113
|
+
},
|
|
9114
|
+
{
|
|
9115
|
+
"slug": "refutes",
|
|
9116
|
+
"displayName": "Refutes",
|
|
9117
|
+
"description": "The source is evidence that the target is false. Kept as a first-class edge so a refuted component stays in the graph with its refutation attached, instead of being quietly deleted \u2014 the reason a road was not taken is worth more than the road.",
|
|
9118
|
+
"isDirectional": true,
|
|
9119
|
+
"uiHints": {
|
|
9120
|
+
"category": "reference",
|
|
9121
|
+
"inverseLabel": "Refuted By"
|
|
9122
|
+
}
|
|
9123
|
+
}
|
|
9124
|
+
],
|
|
9125
|
+
"entityLinks": [
|
|
9126
|
+
{
|
|
9127
|
+
"sourceProfileSlug": "offer",
|
|
9128
|
+
"targetProfileSlug": "convention",
|
|
9129
|
+
"type": "rests_on",
|
|
9130
|
+
"label": "Rests on"
|
|
9131
|
+
},
|
|
9132
|
+
{
|
|
9133
|
+
"sourceProfileSlug": "offer",
|
|
9134
|
+
"targetProfileSlug": "audience",
|
|
9135
|
+
"type": "rests_on",
|
|
9136
|
+
"label": "Rests on"
|
|
9137
|
+
},
|
|
9138
|
+
{
|
|
9139
|
+
"sourceProfileSlug": "projection",
|
|
9140
|
+
"targetProfileSlug": "offer",
|
|
9141
|
+
"type": "rests_on",
|
|
9142
|
+
"label": "Rests on"
|
|
9143
|
+
},
|
|
9144
|
+
{
|
|
9145
|
+
"sourceProfileSlug": "decision",
|
|
9146
|
+
"targetProfileSlug": "convention",
|
|
9147
|
+
"type": "rests_on",
|
|
9148
|
+
"label": "Rests on"
|
|
9149
|
+
},
|
|
9150
|
+
{
|
|
9151
|
+
"sourceProfileSlug": "decision",
|
|
9152
|
+
"targetProfileSlug": "projection",
|
|
9153
|
+
"type": "rests_on",
|
|
9154
|
+
"label": "Rests on"
|
|
9155
|
+
},
|
|
9156
|
+
{
|
|
9157
|
+
"sourceProfileSlug": "convention",
|
|
9158
|
+
"targetProfileSlug": "offer",
|
|
9159
|
+
"type": "refutes",
|
|
9160
|
+
"label": "Refutes"
|
|
9161
|
+
},
|
|
9162
|
+
{
|
|
9163
|
+
"sourceProfileSlug": "convention",
|
|
9164
|
+
"targetProfileSlug": "audience",
|
|
9165
|
+
"type": "refutes",
|
|
9166
|
+
"label": "Refutes"
|
|
9167
|
+
},
|
|
9168
|
+
{
|
|
9169
|
+
"sourceProfileSlug": "convention",
|
|
9170
|
+
"targetProfileSlug": "question",
|
|
9171
|
+
"type": "rests_on",
|
|
9172
|
+
"label": "Rests on"
|
|
9173
|
+
}
|
|
9174
|
+
],
|
|
9175
|
+
"views": [
|
|
9176
|
+
{
|
|
9177
|
+
"name": "Conventions",
|
|
9178
|
+
"slug": "business-model-conventions",
|
|
9179
|
+
"type": "table",
|
|
9180
|
+
"scopeProfileSlug": "convention",
|
|
9181
|
+
"description": "Every rule the model must satisfy, who imposes it, and whether anyone has actually verified it.",
|
|
9182
|
+
"defaultView": true,
|
|
9183
|
+
"config": {
|
|
9184
|
+
"columns": [
|
|
9185
|
+
"title",
|
|
9186
|
+
"conventionType",
|
|
9187
|
+
"issuer",
|
|
9188
|
+
"bindingStatus",
|
|
9189
|
+
"expiresAt"
|
|
9190
|
+
]
|
|
9191
|
+
}
|
|
9192
|
+
},
|
|
9193
|
+
{
|
|
9194
|
+
"name": "Unverified Conventions",
|
|
9195
|
+
"slug": "business-model-assumed-conventions",
|
|
9196
|
+
"type": "list",
|
|
9197
|
+
"scopeProfileSlug": "convention",
|
|
9198
|
+
"description": "Conventions still marked assumed or contested \u2014 the model rests on these and nobody has read the source text.",
|
|
9199
|
+
"config": {
|
|
9200
|
+
"filters": [
|
|
9201
|
+
{
|
|
9202
|
+
"field": "bindingStatus",
|
|
9203
|
+
"operator": "in",
|
|
9204
|
+
"value": [
|
|
9205
|
+
"assumed",
|
|
9206
|
+
"contested"
|
|
9207
|
+
]
|
|
9208
|
+
}
|
|
9209
|
+
]
|
|
9210
|
+
}
|
|
9211
|
+
},
|
|
9212
|
+
{
|
|
9213
|
+
"name": "Projections",
|
|
9214
|
+
"slug": "business-model-projections",
|
|
9215
|
+
"type": "table",
|
|
9216
|
+
"scopeProfileSlug": "projection",
|
|
9217
|
+
"description": "Scenarios with their assumptions in the open, so a number can be argued with.",
|
|
9218
|
+
"config": {
|
|
9219
|
+
"columns": [
|
|
9220
|
+
"title",
|
|
9221
|
+
"scenario",
|
|
9222
|
+
"horizon",
|
|
9223
|
+
"revenueEstimate",
|
|
9224
|
+
"costEstimate",
|
|
9225
|
+
"confidence"
|
|
9226
|
+
]
|
|
9227
|
+
}
|
|
9228
|
+
},
|
|
9229
|
+
{
|
|
9230
|
+
"name": "Open Interrogation",
|
|
9231
|
+
"slug": "business-model-open-questions",
|
|
9232
|
+
"type": "kanban",
|
|
9233
|
+
"scopeProfileSlug": "question",
|
|
9234
|
+
"groupBy": "questionStatus",
|
|
9235
|
+
"description": "The nine component questions and everything they spawned, by status."
|
|
9236
|
+
}
|
|
9237
|
+
],
|
|
9238
|
+
"seedEntities": [
|
|
9239
|
+
{
|
|
9240
|
+
"profileSlug": "question",
|
|
9241
|
+
"title": "Who is the porteur, and what does the model rest on them for?",
|
|
9242
|
+
"properties": {
|
|
9243
|
+
"questionStatus": "open"
|
|
9244
|
+
},
|
|
9245
|
+
"content": "Name the person, then name the specific competence, network, capital, or legitimacy the model cannot survive without. If the answer is generic, the model has no porteur \u2014 it has a job posting."
|
|
9246
|
+
},
|
|
9247
|
+
{
|
|
9248
|
+
"profileSlug": "question",
|
|
9249
|
+
"title": "What does the porteur's situation forbid?",
|
|
9250
|
+
"properties": {
|
|
9251
|
+
"questionStatus": "open"
|
|
9252
|
+
},
|
|
9253
|
+
"content": "Runway, hours available, geography, non-compete, dependants, health. Constraints discovered in month four were knowable in week one."
|
|
9254
|
+
},
|
|
9255
|
+
{
|
|
9256
|
+
"profileSlug": "question",
|
|
9257
|
+
"title": "What is the offer, stated as the problem it ends?",
|
|
9258
|
+
"properties": {
|
|
9259
|
+
"questionStatus": "open"
|
|
9260
|
+
},
|
|
9261
|
+
"content": "Not a description of what is built \u2014 a statement of the situation a buyer is in before, and after. If the offer can only be described by its features, the buyer has not been found yet."
|
|
9262
|
+
},
|
|
9263
|
+
{
|
|
9264
|
+
"profileSlug": "question",
|
|
9265
|
+
"title": "Who exactly buys it, and who merely benefits from it?",
|
|
9266
|
+
"properties": {
|
|
9267
|
+
"questionStatus": "open"
|
|
9268
|
+
},
|
|
9269
|
+
"content": "Link to `audience` entities. Payer, user, and beneficiary are frequently three different parties, and a model that conflates them forecasts revenue from people who never pay."
|
|
9270
|
+
},
|
|
9271
|
+
{
|
|
9272
|
+
"profileSlug": "question",
|
|
9273
|
+
"title": "Which conventions bind this model, and which are still assumed?",
|
|
9274
|
+
"properties": {
|
|
9275
|
+
"questionStatus": "open"
|
|
9276
|
+
},
|
|
9277
|
+
"content": "Eligibility thresholds, professional duties, platform policies, fiscal regimes. Every convention starts `assumed`; the work is reading the source text and moving it to `verified`. An eligibility collision \u2014 where the segment with the most pull sits outside the scheme that would fund it \u2014 only becomes visible once the numbers are pulled."
|
|
9278
|
+
},
|
|
9279
|
+
{
|
|
9280
|
+
"profileSlug": "question",
|
|
9281
|
+
"title": "What does one unit of delivery actually cost to produce?",
|
|
9282
|
+
"properties": {
|
|
9283
|
+
"questionStatus": "open"
|
|
9284
|
+
},
|
|
9285
|
+
"content": "Time, tooling, subcontracting, the unbilled parts. Link the answer to a `projection` so the assumptions stay attached to the number."
|
|
9286
|
+
},
|
|
9287
|
+
{
|
|
9288
|
+
"profileSlug": "question",
|
|
9289
|
+
"title": "Where does the money come from before revenue does?",
|
|
9290
|
+
"properties": {
|
|
9291
|
+
"questionStatus": "open"
|
|
9292
|
+
},
|
|
9293
|
+
"content": "Attach `funder` roles to the companies or schemes involved, with their eligibility conditions. Subsidy is a credential and a discount; it is rarely a pipeline."
|
|
9294
|
+
},
|
|
9295
|
+
{
|
|
9296
|
+
"profileSlug": "question",
|
|
9297
|
+
"title": "What means \u2014 people, tools, licences, premises \u2014 must exist first?",
|
|
9298
|
+
"properties": {
|
|
9299
|
+
"questionStatus": "open"
|
|
9300
|
+
},
|
|
9301
|
+
"content": "The means rest on the money and the money rests on the offer. That circularity is the model, not a planning error; record it with `rests_on` and stop trying to linearise it."
|
|
9302
|
+
},
|
|
9303
|
+
{
|
|
9304
|
+
"profileSlug": "question",
|
|
9305
|
+
"title": "What observation would refute this model, and by when?",
|
|
9306
|
+
"properties": {
|
|
9307
|
+
"questionStatus": "open"
|
|
9308
|
+
},
|
|
9309
|
+
"content": "Set the falsifiable test now, while it can still be set honestly. A model with no refuting observation is a belief with a spreadsheet attached."
|
|
9310
|
+
}
|
|
9311
|
+
],
|
|
9312
|
+
"suggestedRelations": [
|
|
9313
|
+
{
|
|
9314
|
+
"sourceRef": "What is the offer, stated as the problem it ends?",
|
|
9315
|
+
"targetRef": "Who exactly buys it, and who merely benefits from it?",
|
|
9316
|
+
"type": "rests_on"
|
|
9317
|
+
},
|
|
9318
|
+
{
|
|
9319
|
+
"sourceRef": "What is the offer, stated as the problem it ends?",
|
|
9320
|
+
"targetRef": "What means \u2014 people, tools, licences, premises \u2014 must exist first?",
|
|
9321
|
+
"type": "rests_on"
|
|
9322
|
+
},
|
|
9323
|
+
{
|
|
9324
|
+
"sourceRef": "What means \u2014 people, tools, licences, premises \u2014 must exist first?",
|
|
9325
|
+
"targetRef": "Where does the money come from before revenue does?",
|
|
9326
|
+
"type": "rests_on"
|
|
9327
|
+
},
|
|
9328
|
+
{
|
|
9329
|
+
"sourceRef": "Where does the money come from before revenue does?",
|
|
9330
|
+
"targetRef": "What is the offer, stated as the problem it ends?",
|
|
9331
|
+
"type": "rests_on"
|
|
9332
|
+
},
|
|
9333
|
+
{
|
|
9334
|
+
"sourceRef": "Where does the money come from before revenue does?",
|
|
9335
|
+
"targetRef": "Which conventions bind this model, and which are still assumed?",
|
|
9336
|
+
"type": "rests_on"
|
|
9337
|
+
},
|
|
9338
|
+
{
|
|
9339
|
+
"sourceRef": "Who exactly buys it, and who merely benefits from it?",
|
|
9340
|
+
"targetRef": "Which conventions bind this model, and which are still assumed?",
|
|
9341
|
+
"type": "rests_on"
|
|
9342
|
+
},
|
|
9343
|
+
{
|
|
9344
|
+
"sourceRef": "What does one unit of delivery actually cost to produce?",
|
|
9345
|
+
"targetRef": "What does the porteur's situation forbid?",
|
|
9346
|
+
"type": "rests_on"
|
|
9347
|
+
},
|
|
9348
|
+
{
|
|
9349
|
+
"sourceRef": "What is the offer, stated as the problem it ends?",
|
|
9350
|
+
"targetRef": "Who is the porteur, and what does the model rest on them for?",
|
|
9351
|
+
"type": "rests_on"
|
|
9352
|
+
}
|
|
9353
|
+
],
|
|
9354
|
+
"playbooks": [
|
|
9355
|
+
{
|
|
9356
|
+
"name": "Business Model Interrogation",
|
|
9357
|
+
"description": "Walk the nine components as questions, resolve each into a decision backed by evidence, and record the conventions and projections the model rests on \u2014 including the cycles.",
|
|
9358
|
+
"goalTemplate": "Interrogate the business model for {venture} and record what it rests on. Steps: (1) Walk each of the nine seeded `question` entities in this workspace; where one is already answered, mark it and move on. (2) Resolve each into a `decision`, keeping the options that lost attached via `refutes` rather than deleting them. Where the evidence itself needs gathering, do that in the Research workspace and link back \u2014 do not restate sources here. (3) Every external rule discovered becomes a `convention` with its `issuer` and `sourceReference`; leave `bindingStatus` at `assumed` until the source text has actually been read, then `verified`. (4) Every number becomes a `projection` with its `assumptions` filled in \u2014 never a bare figure. (5) Wire the graph with `rests_on` \u2014 offer on audience, projection on offer, decision on convention. Do NOT try to make the graph acyclic: if the offer rests on the means and the means rest on the money and the money rests on the offer, record all three. (6) Attach `porteur` and `funder` roles to the real people and organisations instead of creating new entities for them. (7) Close by listing which conventions are still `assumed` and which projections carry `low` confidence \u2014 that list is the actual state of the model.",
|
|
9359
|
+
"icon": "layout-grid"
|
|
9360
|
+
}
|
|
9361
|
+
],
|
|
9362
|
+
"actionPlacements": [
|
|
9363
|
+
{
|
|
9364
|
+
"profileSlug": "question",
|
|
9365
|
+
"surface": "entity-detail",
|
|
9366
|
+
"kind": "playbook",
|
|
9367
|
+
"ref": "Business Model Interrogation",
|
|
9368
|
+
"label": "Interrogate as model component"
|
|
9369
|
+
},
|
|
9370
|
+
{
|
|
9371
|
+
"profileSlug": "convention",
|
|
9372
|
+
"surface": "entity-detail",
|
|
9373
|
+
"kind": "playbook",
|
|
9374
|
+
"ref": "Business Model Interrogation",
|
|
9375
|
+
"label": "Re-check what rests on this"
|
|
9376
|
+
}
|
|
9377
|
+
],
|
|
9378
|
+
"integrations": [
|
|
9379
|
+
{
|
|
9380
|
+
"templateKey": "research-methods"
|
|
9381
|
+
},
|
|
9382
|
+
{
|
|
9383
|
+
"templateKey": "exa"
|
|
9384
|
+
}
|
|
9385
|
+
]
|
|
9386
|
+
},
|
|
9387
|
+
"civic-france": {
|
|
9388
|
+
"meta": {
|
|
9389
|
+
"slug": "civic-france",
|
|
9390
|
+
"domain": "knowledge",
|
|
9391
|
+
"name": "France Civic Research",
|
|
9392
|
+
"description": "Overlay for investigating French public data (open data / Licence Ouverte). Composes onto Research. Not a government product \u2014 a private research stub.",
|
|
9393
|
+
"icon": "landmark",
|
|
9394
|
+
"color": "#1D4ED8",
|
|
9395
|
+
"tags": [
|
|
9396
|
+
"research",
|
|
9397
|
+
"civic",
|
|
9398
|
+
"france",
|
|
9399
|
+
"open-data",
|
|
9400
|
+
"licence-ouverte"
|
|
9401
|
+
],
|
|
9402
|
+
"isPublic": false
|
|
9403
|
+
},
|
|
9404
|
+
"workspace": {
|
|
9405
|
+
"name": "Research",
|
|
9406
|
+
"description": "Adds a French civic open-data lens onto the Research substrate \u2014 track public datasets consulted during investigations.",
|
|
9407
|
+
"subtype": "research-base"
|
|
9408
|
+
},
|
|
9409
|
+
"dependencies": [
|
|
9410
|
+
{
|
|
9411
|
+
"slug": "research-base",
|
|
9412
|
+
"relation": "compose",
|
|
9413
|
+
"reason": "France civic research is a research method \u2014 it needs the Research substrate (question / research / source) to work over."
|
|
9414
|
+
}
|
|
9415
|
+
],
|
|
9416
|
+
"profiles": [
|
|
9417
|
+
{
|
|
9418
|
+
"slug": "question",
|
|
9419
|
+
"displayName": "Question",
|
|
9420
|
+
"icon": "help-circle",
|
|
9421
|
+
"color": "blue",
|
|
9422
|
+
"description": "An open question driving a civic-data investigation.",
|
|
9423
|
+
"properties": [
|
|
9424
|
+
{
|
|
9425
|
+
"slug": "questionStatus",
|
|
9426
|
+
"label": "Status",
|
|
9427
|
+
"valueType": "string",
|
|
9428
|
+
"inputType": "select",
|
|
9429
|
+
"enumValues": [
|
|
9430
|
+
"open",
|
|
9431
|
+
"exploring",
|
|
9432
|
+
"answered",
|
|
9433
|
+
"abandoned"
|
|
9434
|
+
],
|
|
9435
|
+
"constraints": {
|
|
9436
|
+
"defaultValue": "open"
|
|
9437
|
+
}
|
|
9438
|
+
}
|
|
9439
|
+
]
|
|
9440
|
+
},
|
|
9441
|
+
{
|
|
9442
|
+
"slug": "research",
|
|
9443
|
+
"displayName": "Research",
|
|
9444
|
+
"icon": "microscope",
|
|
9445
|
+
"color": "violet",
|
|
9446
|
+
"description": "An investigation into French public data \u2014 sources, findings, conclusion.",
|
|
9447
|
+
"properties": [
|
|
9448
|
+
{
|
|
9449
|
+
"slug": "researchStatus",
|
|
9450
|
+
"label": "Status",
|
|
9451
|
+
"valueType": "string",
|
|
9452
|
+
"inputType": "select",
|
|
9453
|
+
"enumValues": [
|
|
9454
|
+
"ongoing",
|
|
9455
|
+
"concluded",
|
|
9456
|
+
"abandoned"
|
|
9457
|
+
],
|
|
9458
|
+
"constraints": {
|
|
9459
|
+
"defaultValue": "ongoing"
|
|
9460
|
+
}
|
|
9461
|
+
}
|
|
9462
|
+
]
|
|
9463
|
+
},
|
|
9464
|
+
{
|
|
9465
|
+
"slug": "source",
|
|
9466
|
+
"displayName": "Source",
|
|
9467
|
+
"icon": "file-text",
|
|
9468
|
+
"color": "cyan",
|
|
9469
|
+
"description": "Anything consulted \u2014 API payload, dataset page, decree, report.",
|
|
9470
|
+
"properties": [
|
|
9471
|
+
{
|
|
9472
|
+
"slug": "url",
|
|
9473
|
+
"label": "URL",
|
|
9474
|
+
"valueType": "string",
|
|
9475
|
+
"inputType": "url"
|
|
9476
|
+
}
|
|
9477
|
+
]
|
|
9478
|
+
},
|
|
9479
|
+
{
|
|
9480
|
+
"slug": "public_dataset",
|
|
9481
|
+
"displayName": "Public dataset",
|
|
9482
|
+
"icon": "database",
|
|
9483
|
+
"color": "blue",
|
|
9484
|
+
"description": "A French public dataset consulted via official open-data APIs (data.gouv.fr / api.gouv.fr / PISTE) \u2014 never scraped HTML.",
|
|
9485
|
+
"scope": "WORKSPACE",
|
|
9486
|
+
"properties": [
|
|
9487
|
+
{
|
|
9488
|
+
"slug": "sourceUrl",
|
|
9489
|
+
"label": "Source URL",
|
|
9490
|
+
"valueType": "string",
|
|
9491
|
+
"inputType": "url"
|
|
9492
|
+
},
|
|
9493
|
+
{
|
|
9494
|
+
"slug": "license",
|
|
9495
|
+
"label": "License",
|
|
9496
|
+
"valueType": "string",
|
|
9497
|
+
"inputType": "text"
|
|
9498
|
+
},
|
|
9499
|
+
{
|
|
9500
|
+
"slug": "publisher",
|
|
9501
|
+
"label": "Publisher",
|
|
9502
|
+
"valueType": "string",
|
|
9503
|
+
"inputType": "text"
|
|
9504
|
+
}
|
|
9505
|
+
]
|
|
9506
|
+
}
|
|
9507
|
+
],
|
|
9508
|
+
"views": [
|
|
9509
|
+
{
|
|
9510
|
+
"name": "Public datasets",
|
|
9511
|
+
"slug": "civic-france-public-datasets",
|
|
9512
|
+
"type": "table",
|
|
9513
|
+
"scopeProfileSlug": "public_dataset",
|
|
9514
|
+
"description": "French public datasets tracked in this research workspace.",
|
|
9515
|
+
"config": {
|
|
9516
|
+
"columns": [
|
|
9517
|
+
"title",
|
|
9518
|
+
"publisher",
|
|
9519
|
+
"license",
|
|
9520
|
+
"sourceUrl"
|
|
9521
|
+
]
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9524
|
+
]
|
|
9525
|
+
},
|
|
8879
9526
|
"communication": {
|
|
8880
9527
|
"meta": {
|
|
8881
9528
|
"slug": "communication",
|
|
@@ -16036,6 +16683,95 @@ document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
|
16036
16683
|
"inputType": "textarea"
|
|
16037
16684
|
}
|
|
16038
16685
|
]
|
|
16686
|
+
},
|
|
16687
|
+
{
|
|
16688
|
+
"slug": "porteur",
|
|
16689
|
+
"displayName": "Porteur",
|
|
16690
|
+
"icon": "user-check",
|
|
16691
|
+
"color": "amber",
|
|
16692
|
+
"description": "The person carrying a venture \u2014 the one whose commitment, skills, and constraints the model actually rests on. Distinct from `client` (who pays) and `partner` (who collaborates).",
|
|
16693
|
+
"scope": "shared",
|
|
16694
|
+
"profileKind": "role",
|
|
16695
|
+
"applicableKinds": [
|
|
16696
|
+
"person"
|
|
16697
|
+
],
|
|
16698
|
+
"properties": [
|
|
16699
|
+
{
|
|
16700
|
+
"slug": "brings",
|
|
16701
|
+
"label": "What They Bring",
|
|
16702
|
+
"valueType": "string",
|
|
16703
|
+
"inputType": "textarea",
|
|
16704
|
+
"description": "The specific competence, network, capital, or legitimacy this person contributes that the model depends on."
|
|
16705
|
+
},
|
|
16706
|
+
{
|
|
16707
|
+
"slug": "commitmentLevel",
|
|
16708
|
+
"label": "Commitment",
|
|
16709
|
+
"valueType": "string",
|
|
16710
|
+
"inputType": "select",
|
|
16711
|
+
"enumValues": [
|
|
16712
|
+
"full-time",
|
|
16713
|
+
"part-time",
|
|
16714
|
+
"advisory",
|
|
16715
|
+
"intermittent"
|
|
16716
|
+
]
|
|
16717
|
+
},
|
|
16718
|
+
{
|
|
16719
|
+
"slug": "constraints",
|
|
16720
|
+
"label": "Constraints",
|
|
16721
|
+
"valueType": "string",
|
|
16722
|
+
"inputType": "textarea",
|
|
16723
|
+
"description": "What limits this porteur \u2014 time, cash runway, geography, non-compete, family. A model that ignores these is fiction."
|
|
16724
|
+
}
|
|
16725
|
+
]
|
|
16726
|
+
},
|
|
16727
|
+
{
|
|
16728
|
+
"slug": "funder",
|
|
16729
|
+
"displayName": "Funder",
|
|
16730
|
+
"icon": "banknote",
|
|
16731
|
+
"color": "green",
|
|
16732
|
+
"description": "A source of non-revenue money or subsidy \u2014 a bank, a public scheme, an investor, a grantor. A hat worn by a company or a person, never a kind of its own.",
|
|
16733
|
+
"scope": "shared",
|
|
16734
|
+
"profileKind": "role",
|
|
16735
|
+
"applicableKinds": [
|
|
16736
|
+
"company",
|
|
16737
|
+
"person"
|
|
16738
|
+
],
|
|
16739
|
+
"properties": [
|
|
16740
|
+
{
|
|
16741
|
+
"slug": "fundingType",
|
|
16742
|
+
"label": "Funding Type",
|
|
16743
|
+
"valueType": "string",
|
|
16744
|
+
"inputType": "select",
|
|
16745
|
+
"enumValues": [
|
|
16746
|
+
"grant",
|
|
16747
|
+
"subsidy",
|
|
16748
|
+
"loan",
|
|
16749
|
+
"equity",
|
|
16750
|
+
"guarantee",
|
|
16751
|
+
"prize",
|
|
16752
|
+
"other"
|
|
16753
|
+
]
|
|
16754
|
+
},
|
|
16755
|
+
{
|
|
16756
|
+
"slug": "amountCommitted",
|
|
16757
|
+
"label": "Amount Committed",
|
|
16758
|
+
"valueType": "number",
|
|
16759
|
+
"inputType": "number"
|
|
16760
|
+
},
|
|
16761
|
+
{
|
|
16762
|
+
"slug": "eligibilityConditions",
|
|
16763
|
+
"label": "Eligibility Conditions",
|
|
16764
|
+
"valueType": "string",
|
|
16765
|
+
"inputType": "textarea",
|
|
16766
|
+
"description": "The conditions the venture must satisfy to keep this money. These are the constraints most often discovered too late."
|
|
16767
|
+
},
|
|
16768
|
+
{
|
|
16769
|
+
"slug": "decisionDate",
|
|
16770
|
+
"label": "Decision Date",
|
|
16771
|
+
"valueType": "date",
|
|
16772
|
+
"inputType": "date"
|
|
16773
|
+
}
|
|
16774
|
+
]
|
|
16039
16775
|
}
|
|
16040
16776
|
],
|
|
16041
16777
|
"views": [
|
|
@@ -17622,40 +18358,47 @@ document. No preamble, no explanation, no code fences around the whole thing.`,
|
|
|
17622
18358
|
"required": true
|
|
17623
18359
|
}
|
|
17624
18360
|
],
|
|
18361
|
+
"scope": "project",
|
|
17625
18362
|
"stages": [
|
|
17626
18363
|
{
|
|
17627
18364
|
"key": "identify",
|
|
17628
18365
|
"name": "Identify",
|
|
18366
|
+
"category": "planned",
|
|
17629
18367
|
"description": "Understand the project and which of the program's submission tracks fit \u2014 before any writing.",
|
|
17630
18368
|
"goal": "A clear project understanding and the fitting submission track; submission stage = scope."
|
|
17631
18369
|
},
|
|
17632
18370
|
{
|
|
17633
18371
|
"key": "draft",
|
|
17634
18372
|
"name": "Draft",
|
|
18373
|
+
"category": "started",
|
|
17635
18374
|
"description": "Write the abstract, then the full proposal, from the client's real material.",
|
|
17636
18375
|
"goal": "Abstract then full proposal drafted; submission stage abstract \u2192 build with body fields filled."
|
|
17637
18376
|
},
|
|
17638
18377
|
{
|
|
17639
18378
|
"key": "submit",
|
|
17640
18379
|
"name": "Submit",
|
|
18380
|
+
"category": "started",
|
|
17641
18381
|
"description": "Finalize against the program deadline and submit the application.",
|
|
17642
18382
|
"goal": "Application submitted on time; submission stage = awaiting-results."
|
|
17643
18383
|
},
|
|
17644
18384
|
{
|
|
17645
18385
|
"key": "awaiting",
|
|
17646
18386
|
"name": "Awaiting",
|
|
18387
|
+
"category": "paused",
|
|
17647
18388
|
"description": "Track the decision and keep the client status current.",
|
|
17648
18389
|
"goal": "Submission status reflects where the decision stands (in-review / waiting-client / needs-document / blocked)."
|
|
17649
18390
|
},
|
|
17650
18391
|
{
|
|
17651
18392
|
"key": "awarded",
|
|
17652
18393
|
"name": "Awarded",
|
|
18394
|
+
"category": "started",
|
|
17653
18395
|
"description": "Record the funder's decision and the awarded amount.",
|
|
17654
18396
|
"goal": "Submission outcome set (awarded / rejected / partial) with the awarded amount."
|
|
17655
18397
|
},
|
|
17656
18398
|
{
|
|
17657
18399
|
"key": "delivering",
|
|
17658
18400
|
"name": "Delivering",
|
|
18401
|
+
"category": "started",
|
|
17659
18402
|
"description": "Work the program's tranche model \u2014 ship and record each tranche.",
|
|
17660
18403
|
"goal": "Tranche deliverables filled and trancheCompletion updated as milestones ship."
|
|
17661
18404
|
}
|
|
@@ -21689,6 +22432,19 @@ Report the submission's current state as STRICT JSON, using ONLY these vocabular
|
|
|
21689
22432
|
}
|
|
21690
22433
|
],
|
|
21691
22434
|
"views": [
|
|
22435
|
+
{
|
|
22436
|
+
"name": "Knowledge",
|
|
22437
|
+
"slug": "knowledge",
|
|
22438
|
+
"type": "table",
|
|
22439
|
+
"scopeProfileSlug": "knowledge",
|
|
22440
|
+
"description": "Validated insights and cautions, with their long-form context and evidence kept in the graph.",
|
|
22441
|
+
"config": {
|
|
22442
|
+
"columns": [
|
|
22443
|
+
"title",
|
|
22444
|
+
"knowledgeForm"
|
|
22445
|
+
]
|
|
22446
|
+
}
|
|
22447
|
+
},
|
|
21692
22448
|
{
|
|
21693
22449
|
"name": "All Notes",
|
|
21694
22450
|
"type": "table",
|
|
@@ -22527,6 +23283,12 @@ Report the submission's current state as STRICT JSON, using ONLY these vocabular
|
|
|
22527
23283
|
"label": "Brain Home",
|
|
22528
23284
|
"icon": "Home"
|
|
22529
23285
|
},
|
|
23286
|
+
{
|
|
23287
|
+
"kind": "profile",
|
|
23288
|
+
"profileSlug": "knowledge",
|
|
23289
|
+
"label": "Knowledge",
|
|
23290
|
+
"icon": "Brain"
|
|
23291
|
+
},
|
|
22530
23292
|
{
|
|
22531
23293
|
"kind": "profile",
|
|
22532
23294
|
"profileSlug": "note",
|
|
@@ -30442,6 +31204,7 @@ function rowToRemoteEntry(row, isPrivate) {
|
|
|
30442
31204
|
tags: row.tags ?? [],
|
|
30443
31205
|
icon: row.icon ?? null,
|
|
30444
31206
|
isPrivate,
|
|
31207
|
+
requiredTier: row.requiredTier ?? null,
|
|
30445
31208
|
items: row.items
|
|
30446
31209
|
// Both list routes strip `definition`; absence ⇒ bundle wins a slug conflict,
|
|
30447
31210
|
// and the install path fetches the full definition per-slug when needed.
|
|
@@ -30478,6 +31241,8 @@ function bundledToEntry(tpl) {
|
|
|
30478
31241
|
tags: tpl.meta.tags ?? [],
|
|
30479
31242
|
icon: tpl.meta.icon,
|
|
30480
31243
|
isPrivate: tpl.meta.isPublic === false,
|
|
31244
|
+
// Bundled templates ship in-client and are never tier-gated.
|
|
31245
|
+
requiredTier: null,
|
|
30481
31246
|
// Bundled workspace templates carry no cells — be honest, not `undefined`.
|
|
30482
31247
|
items: [],
|
|
30483
31248
|
template: tpl
|
|
@@ -30494,6 +31259,7 @@ function remoteToEntry(row) {
|
|
|
30494
31259
|
tags: row.tags ?? [],
|
|
30495
31260
|
icon: row.icon ?? null,
|
|
30496
31261
|
isPrivate: row.isPrivate ?? false,
|
|
31262
|
+
requiredTier: row.requiredTier ?? null,
|
|
30497
31263
|
items: row.items ?? [],
|
|
30498
31264
|
remote: row
|
|
30499
31265
|
};
|
|
@@ -31230,7 +31996,10 @@ function collectLoopBindingRefs(data) {
|
|
|
31230
31996
|
return;
|
|
31231
31997
|
}
|
|
31232
31998
|
if (isRecord(v)) {
|
|
31233
|
-
for (const x of Object.
|
|
31999
|
+
for (const [k, x] of Object.entries(v)) {
|
|
32000
|
+
if (k.startsWith("_")) continue;
|
|
32001
|
+
walk(x);
|
|
32002
|
+
}
|
|
31234
32003
|
}
|
|
31235
32004
|
};
|
|
31236
32005
|
walk(data);
|
|
@@ -31313,6 +32082,9 @@ var SYSTEM_PROFILES = /* @__PURE__ */ new Set([
|
|
|
31313
32082
|
// `create-report` node references it, so referential integrity needs it here.
|
|
31314
32083
|
"report"
|
|
31315
32084
|
]);
|
|
32085
|
+
var TEMPLATE_FORBIDDEN_SYSTEM_PROFILE_SLUGS = /* @__PURE__ */ new Set(["knowledge"]);
|
|
32086
|
+
var KNOWLEDGE_FORMS = /* @__PURE__ */ new Set(["insight", "caution"]);
|
|
32087
|
+
var LEGACY_KNOWLEDGE_SEED_FIELDS = /* @__PURE__ */ new Set(["ek_type", "type"]);
|
|
31316
32088
|
function isPodWideProfile(p) {
|
|
31317
32089
|
return String(p.scope || "").toLowerCase() === "shared";
|
|
31318
32090
|
}
|
|
@@ -31456,6 +32228,14 @@ function validateTemplate(tpl, opts = {}) {
|
|
|
31456
32228
|
const baseProfileSlugs = collectBaseProfileSlugs(tpl, resolveDepFrom(opts));
|
|
31457
32229
|
const slugs = new Set((tpl.profiles || []).map((p) => p.slug));
|
|
31458
32230
|
const known = (s) => slugs.has(s) || SYSTEM_PROFILES.has(s) || baseProfileSlugs.has(s);
|
|
32231
|
+
for (const profile of tpl.profiles || []) {
|
|
32232
|
+
if (!TEMPLATE_FORBIDDEN_SYSTEM_PROFILE_SLUGS.has(profile.slug)) continue;
|
|
32233
|
+
add(
|
|
32234
|
+
"system-profile-redefined",
|
|
32235
|
+
`profiles.${profile.slug}`,
|
|
32236
|
+
`Profile "${profile.slug}" is system-owned. Reference it from views, links, sidebar items, or seedEntities; do not declare template-owned properties or metadata.`
|
|
32237
|
+
);
|
|
32238
|
+
}
|
|
31459
32239
|
for (const v of tpl.views || []) {
|
|
31460
32240
|
const type = String(v.type || "").toLowerCase();
|
|
31461
32241
|
const scoped = v.scopeProfileSlug || v.scopeProfileSlugs && v.scopeProfileSlugs.length;
|
|
@@ -31605,6 +32385,24 @@ function validateTemplate(tpl, opts = {}) {
|
|
|
31605
32385
|
"seedEntities",
|
|
31606
32386
|
`seedEntity references unknown profile "${s.profileSlug}"`
|
|
31607
32387
|
);
|
|
32388
|
+
if (s.profileSlug !== "knowledge") continue;
|
|
32389
|
+
const properties = s.properties ?? {};
|
|
32390
|
+
for (const field of LEGACY_KNOWLEDGE_SEED_FIELDS) {
|
|
32391
|
+
if (!(field in properties)) continue;
|
|
32392
|
+
add(
|
|
32393
|
+
"knowledge-seed-legacy-form",
|
|
32394
|
+
`seedEntities.${s.title}.properties.${field}`,
|
|
32395
|
+
`Knowledge seed entities use "knowledgeForm" ("insight" | "caution"), not the legacy "${field}" field.`
|
|
32396
|
+
);
|
|
32397
|
+
}
|
|
32398
|
+
const form = properties.knowledgeForm;
|
|
32399
|
+
if (!KNOWLEDGE_FORMS.has(String(form))) {
|
|
32400
|
+
add(
|
|
32401
|
+
"knowledge-seed-form-invalid",
|
|
32402
|
+
`seedEntities.${s.title}.properties.knowledgeForm`,
|
|
32403
|
+
`Knowledge seed entities require knowledgeForm to be "insight" or "caution".`
|
|
32404
|
+
);
|
|
32405
|
+
}
|
|
31608
32406
|
}
|
|
31609
32407
|
for (const a of tpl.automations || []) {
|
|
31610
32408
|
const refs = [];
|