@vectros-ai/blueprints 0.5.0 → 0.6.2

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.mjs CHANGED
@@ -159,11 +159,36 @@ var BlueprintServicePrincipalSchema = z.object({
159
159
  externalId: z.string().min(1),
160
160
  displayName: z.string().min(1)
161
161
  }).strict();
162
- var BlueprintSeedRecordSchema = z.object({
162
+ var SeedCommonShape = {
163
+ /** The schema typeName this seed instantiates (should match a declared schema). */
163
164
  typeName: z.string().min(1),
164
- externalId: z.string().min(1),
165
+ /**
166
+ * Stable, caller-supplied id — the loader's idempotency key AND the value other
167
+ * seeds resolve a `reference` against (across surfaces: a record seed may
168
+ * reference a document seed by its externalId, and vice versa).
169
+ */
170
+ externalId: z.string().min(1)
171
+ };
172
+ var RecordSeedSchema = z.object({
173
+ surface: z.literal("record"),
174
+ ...SeedCommonShape,
175
+ /** The record payload, validated against the bound schema. */
165
176
  fields: z.record(z.unknown())
166
177
  }).strict();
178
+ var DocumentSeedSchema = z.object({
179
+ surface: z.literal("document"),
180
+ ...SeedCommonShape,
181
+ /** Human-readable document title — REQUIRED by the text-ingest path. */
182
+ title: z.string().min(1),
183
+ /** Raw text content to ingest + index — REQUIRED and non-empty (the platform rejects a blank ingest). */
184
+ text: z.string().min(1),
185
+ /** Optional structured payload bound to the schema (the document's `fields`). */
186
+ fields: z.record(z.unknown()).optional()
187
+ }).strict();
188
+ var BlueprintSeedRecordSchema = z.discriminatedUnion("surface", [
189
+ RecordSeedSchema,
190
+ DocumentSeedSchema
191
+ ]);
167
192
  var SELF_TOKEN_RE = /\$\{\{\s*self\.[A-Za-z_]\w*\s*\}\}/;
168
193
  function lintSelfTokenPlacement(value, ctx) {
169
194
  const walk = (node, path, inRoleDataScope) => {
@@ -219,6 +244,23 @@ function lintIdentityRefsDeclared(value, ctx) {
219
244
  };
220
245
  walk(value, []);
221
246
  }
247
+ function lintSeedSurfaces(value, ctx) {
248
+ const bp = value;
249
+ if (!Array.isArray(bp.seed)) return;
250
+ const byType = new Map((bp.schemas ?? []).map((s) => [s.typeName, s]));
251
+ bp.seed.forEach((seed, i) => {
252
+ const schema = byType.get(seed.typeName);
253
+ if (!schema) return;
254
+ const allowed = schema.allowedSurfaces ?? ["record"];
255
+ if (!allowed.includes(seed.surface ?? "record")) {
256
+ ctx.addIssue({
257
+ code: z.ZodIssueCode.custom,
258
+ path: ["seed", i, "surface"],
259
+ message: `seed '${seed.externalId}' uses surface '${seed.surface ?? "record"}', but schema '${seed.typeName}' allows only [${allowed.join(", ")}]`
260
+ });
261
+ }
262
+ });
263
+ }
222
264
  var BlueprintSchema = z.object({
223
265
  /** Stable blueprint id (the `--blueprint <name>` selector + idempotency key). */
224
266
  name: z.string().min(1),
@@ -241,6 +283,7 @@ var BlueprintSchema = z.object({
241
283
  }).strict().superRefine((bp, ctx) => {
242
284
  lintSelfTokenPlacement(bp, ctx);
243
285
  lintIdentityRefsDeclared(bp, ctx);
286
+ lintSeedSurfaces(bp, ctx);
244
287
  });
245
288
  function formatIssuePath(path) {
246
289
  let out = "";
@@ -719,6 +762,7 @@ var taskManagement = {
719
762
  },
720
763
  seed: [
721
764
  {
765
+ surface: "record",
722
766
  typeName: "task",
723
767
  externalId: "seed-welcome",
724
768
  fields: {
@@ -948,6 +992,7 @@ var codingAgentMemory = {
948
992
  // Seeded FIRST so the convention below resolves its reference to it — the
949
993
  // loader creates seeds in array order, and a reference target must exist when
950
994
  // the referencing record is written.
995
+ surface: "record",
951
996
  typeName: "decision",
952
997
  externalId: "seed-use-vectros-for-memory",
953
998
  fields: {
@@ -963,6 +1008,7 @@ var codingAgentMemory = {
963
1008
  // Demonstrates a live typed link at bootstrap: this convention references the
964
1009
  // decision above by its externalId, so "open the decision behind this rule"
965
1010
  // works the moment the blueprint is applied.
1011
+ surface: "record",
966
1012
  typeName: "convention",
967
1013
  externalId: "seed-record-the-why",
968
1014
  fields: {
@@ -978,6 +1024,689 @@ var codingAgentMemory = {
978
1024
  };
979
1025
  var coding_agent_memory_default = codingAgentMemory;
980
1026
 
1027
+ // src/blueprints/agentic-sdlc.ts
1028
+ var agenticSdlc = {
1029
+ name: "agentic-sdlc",
1030
+ version: "1.0.0",
1031
+ description: "A whole-SDLC system of record for an AI development team \u2014 decisions, designs, references, runbooks, post-mortems (as documents) plus controls, conventions, gotchas, and a glossary (as records), cross-linked and recalled by meaning.",
1032
+ contextId: "agentic-sdlc",
1033
+ contextName: "Agentic SDLC Knowledge Base",
1034
+ schemas: [
1035
+ // ============================ DOCUMENTS ============================
1036
+ // Content-dominant: the markdown body is the artifact; fields are metadata.
1037
+ // Each binds the `document` surface and is ingested via `document_ingest`.
1038
+ {
1039
+ // An architecture/product DECISION (an ADR). The body is the prose —
1040
+ // Context / Decision / Consequences — and is what `rag_ask` answers over;
1041
+ // the fields below are filter/sort metadata + the supersede chain. The
1042
+ // anchor of the graph: most other types link back to a decision.
1043
+ typeName: "decision",
1044
+ displayName: "Decision (ADR)",
1045
+ indexMode: "HYBRID",
1046
+ allowedSurfaces: ["document"],
1047
+ // A document carries an INTRINSIC title (the ingest title) + body; the schema
1048
+ // declares only the metadata BEYOND those. (No typed `title` field — that
1049
+ // would duplicate the document's own title.)
1050
+ fields: [
1051
+ {
1052
+ fieldId: "summary",
1053
+ fieldType: "string",
1054
+ searchable: true,
1055
+ description: "A one-paragraph abstract of the decision. The full reasoning is the document body.",
1056
+ renderHints: { label: "Summary", widget: "textarea", order: 2 }
1057
+ },
1058
+ {
1059
+ fieldId: "status",
1060
+ fieldType: "enum",
1061
+ filterable: true,
1062
+ enumValues: ["proposed", "accepted", "superseded", "deprecated"],
1063
+ renderHints: { label: "Status", widget: "select", order: 3 }
1064
+ },
1065
+ {
1066
+ fieldId: "area",
1067
+ fieldType: "string",
1068
+ filterable: true,
1069
+ description: 'Subsystem the decision applies to (e.g. "search", "auth", "billing").',
1070
+ renderHints: { label: "Area", widget: "text", order: 4 }
1071
+ },
1072
+ {
1073
+ fieldId: "tags",
1074
+ fieldType: "array",
1075
+ filterable: true,
1076
+ description: 'Freeform labels (e.g. "security", "schema"). Search-side filter.',
1077
+ renderHints: { label: "Tags", order: 5 }
1078
+ },
1079
+ {
1080
+ // Self-reference (document → document): the decision this one supersedes.
1081
+ fieldId: "supersedes",
1082
+ fieldType: "reference",
1083
+ targetTypeName: "decision",
1084
+ targetSurface: "document",
1085
+ targetField: "externalId",
1086
+ cardinality: "one",
1087
+ description: "The decision this one supersedes (by externalId).",
1088
+ renderHints: { label: "Supersedes", order: 6 }
1089
+ },
1090
+ {
1091
+ fieldId: "date",
1092
+ fieldType: "date",
1093
+ description: "ISO-8601 decision date. Range-queryable / sortable.",
1094
+ renderHints: { label: "Date", widget: "date", order: 7 }
1095
+ }
1096
+ ],
1097
+ lookupFields: ["status", "area", "supersedes", { fieldName: "date", rangeEnabled: true }]
1098
+ },
1099
+ {
1100
+ // A DESIGN doc or spec — the exploration that drives a decision. Distinct
1101
+ // from `decision` (a different browse genre + it links to the decision it
1102
+ // informs). Body = the design narrative.
1103
+ typeName: "design",
1104
+ displayName: "Design",
1105
+ indexMode: "HYBRID",
1106
+ allowedSurfaces: ["document"],
1107
+ // Intrinsic title + body; schema = metadata beyond those (no typed `title`).
1108
+ fields: [
1109
+ {
1110
+ fieldId: "summary",
1111
+ fieldType: "string",
1112
+ searchable: true,
1113
+ description: "A one-paragraph abstract. The full design is the document body.",
1114
+ renderHints: { label: "Summary", widget: "textarea", order: 2 }
1115
+ },
1116
+ {
1117
+ fieldId: "status",
1118
+ fieldType: "enum",
1119
+ filterable: true,
1120
+ enumValues: ["draft", "active", "implemented", "superseded"],
1121
+ renderHints: { label: "Status", widget: "select", order: 3 }
1122
+ },
1123
+ {
1124
+ fieldId: "area",
1125
+ fieldType: "string",
1126
+ filterable: true,
1127
+ renderHints: { label: "Area", widget: "text", order: 4 }
1128
+ },
1129
+ {
1130
+ fieldId: "tags",
1131
+ fieldType: "array",
1132
+ filterable: true,
1133
+ renderHints: { label: "Tags", order: 5 }
1134
+ },
1135
+ {
1136
+ // Cross-document edge: the decision this design informs/produces.
1137
+ fieldId: "relatedDecision",
1138
+ fieldType: "reference",
1139
+ targetTypeName: "decision",
1140
+ targetSurface: "document",
1141
+ targetField: "externalId",
1142
+ cardinality: "one",
1143
+ description: "The decision this design informs (by externalId).",
1144
+ renderHints: { label: "Related decision", order: 6 }
1145
+ },
1146
+ {
1147
+ // Self-reference: a design supersedes an earlier design/spec.
1148
+ fieldId: "supersedes",
1149
+ fieldType: "reference",
1150
+ targetTypeName: "design",
1151
+ targetSurface: "document",
1152
+ targetField: "externalId",
1153
+ cardinality: "one",
1154
+ description: "The design this one supersedes (by externalId).",
1155
+ renderHints: { label: "Supersedes", order: 7 }
1156
+ },
1157
+ {
1158
+ fieldId: "updatedOn",
1159
+ fieldType: "date",
1160
+ description: "ISO-8601 \u2014 when last revised. Range-queryable.",
1161
+ renderHints: { label: "Updated on", widget: "date", order: 8 }
1162
+ }
1163
+ ],
1164
+ lookupFields: ["status", "area", "relatedDecision", "supersedes", { fieldName: "updatedOn", rangeEnabled: true }]
1165
+ },
1166
+ {
1167
+ // A REFERENCE doc — maintained "how it works / how to": guides, onboarding,
1168
+ // API docs, process docs. Body = the prose. Distinct shape: a `category`
1169
+ // (DRY sub-labels — onboarding/api/process are same shape) and `lastReviewed`
1170
+ // (freshness is the whole game for reference material).
1171
+ typeName: "reference",
1172
+ displayName: "Reference",
1173
+ indexMode: "HYBRID",
1174
+ allowedSurfaces: ["document"],
1175
+ // Intrinsic title + body; schema = metadata beyond those (no typed `title`).
1176
+ fields: [
1177
+ {
1178
+ fieldId: "summary",
1179
+ fieldType: "string",
1180
+ searchable: true,
1181
+ description: "A one-paragraph abstract. The full reference is the document body.",
1182
+ renderHints: { label: "Summary", widget: "textarea", order: 2 }
1183
+ },
1184
+ {
1185
+ // The sub-kind, as a filterable field (not a separate schema — these are
1186
+ // the same shape, differing only by label, so a field is the DRY choice).
1187
+ fieldId: "category",
1188
+ fieldType: "enum",
1189
+ filterable: true,
1190
+ enumValues: ["guide", "onboarding", "api", "process", "other"],
1191
+ renderHints: { label: "Category", widget: "select", order: 3 }
1192
+ },
1193
+ {
1194
+ fieldId: "area",
1195
+ fieldType: "string",
1196
+ filterable: true,
1197
+ renderHints: { label: "Area", widget: "text", order: 4 }
1198
+ },
1199
+ {
1200
+ fieldId: "tags",
1201
+ fieldType: "array",
1202
+ filterable: true,
1203
+ renderHints: { label: "Tags", order: 5 }
1204
+ },
1205
+ {
1206
+ fieldId: "status",
1207
+ fieldType: "enum",
1208
+ filterable: true,
1209
+ enumValues: ["active", "superseded"],
1210
+ renderHints: { label: "Status", widget: "select", order: 6 }
1211
+ },
1212
+ {
1213
+ // Optional cross-document edge: the decision behind this reference.
1214
+ fieldId: "relatedDecision",
1215
+ fieldType: "reference",
1216
+ targetTypeName: "decision",
1217
+ targetSurface: "document",
1218
+ targetField: "externalId",
1219
+ cardinality: "one",
1220
+ description: "The decision behind this reference, if any (by externalId).",
1221
+ renderHints: { label: "Related decision", order: 7 }
1222
+ },
1223
+ {
1224
+ // Freshness — "references not reviewed since X". The reference-doc signal.
1225
+ fieldId: "lastReviewed",
1226
+ fieldType: "date",
1227
+ description: "ISO-8601 \u2014 when this reference was last verified current. Range-queryable.",
1228
+ renderHints: { label: "Last reviewed", widget: "date", order: 8 }
1229
+ }
1230
+ ],
1231
+ lookupFields: ["category", "area", "status", "relatedDecision", { fieldName: "lastReviewed", rangeEnabled: true }]
1232
+ },
1233
+ {
1234
+ // A RUNBOOK — a step-by-step operational procedure (deploy, release, recover).
1235
+ // Body = the procedure. Distinct browse genre, and often BORN FROM a
1236
+ // post-mortem (its resolution, codified) — a cross-document edge.
1237
+ typeName: "runbook",
1238
+ displayName: "Runbook",
1239
+ indexMode: "HYBRID",
1240
+ allowedSurfaces: ["document"],
1241
+ // Intrinsic title + body; schema = metadata beyond those (no typed `title`).
1242
+ fields: [
1243
+ {
1244
+ fieldId: "summary",
1245
+ fieldType: "string",
1246
+ searchable: true,
1247
+ description: "When to use this runbook \u2014 the trigger. The steps are the document body.",
1248
+ renderHints: { label: "Summary", widget: "textarea", order: 2 }
1249
+ },
1250
+ {
1251
+ fieldId: "area",
1252
+ fieldType: "string",
1253
+ filterable: true,
1254
+ renderHints: { label: "Area", widget: "text", order: 3 }
1255
+ },
1256
+ {
1257
+ fieldId: "tags",
1258
+ fieldType: "array",
1259
+ filterable: true,
1260
+ renderHints: { label: "Tags", order: 4 }
1261
+ },
1262
+ {
1263
+ fieldId: "status",
1264
+ fieldType: "enum",
1265
+ filterable: true,
1266
+ enumValues: ["active", "retired"],
1267
+ renderHints: { label: "Status", widget: "select", order: 5 }
1268
+ },
1269
+ {
1270
+ // Cross-document edge: the post-mortem whose resolution this runbook codifies.
1271
+ fieldId: "bornFrom",
1272
+ fieldType: "reference",
1273
+ targetTypeName: "postmortem",
1274
+ targetSurface: "document",
1275
+ targetField: "externalId",
1276
+ cardinality: "one",
1277
+ description: "The post-mortem this runbook was codified from (by externalId).",
1278
+ renderHints: { label: "Born from (post-mortem)", order: 6 }
1279
+ },
1280
+ {
1281
+ fieldId: "relatedDecision",
1282
+ fieldType: "reference",
1283
+ targetTypeName: "decision",
1284
+ targetSurface: "document",
1285
+ targetField: "externalId",
1286
+ cardinality: "one",
1287
+ description: "A decision this runbook implements, if any (by externalId).",
1288
+ renderHints: { label: "Related decision", order: 7 }
1289
+ },
1290
+ {
1291
+ fieldId: "updatedOn",
1292
+ fieldType: "date",
1293
+ description: "ISO-8601 \u2014 when last revised. Range-queryable.",
1294
+ renderHints: { label: "Updated on", widget: "date", order: 8 }
1295
+ }
1296
+ ],
1297
+ lookupFields: ["area", "status", "bornFrom", "relatedDecision", { fieldName: "updatedOn", rangeEnabled: true }]
1298
+ },
1299
+ {
1300
+ // A POST-MORTEM — what broke and the durable lesson. Body = the writeup
1301
+ // (impact / root cause / resolution / lesson). Distinct shape: `severity` +
1302
+ // `occurredOn` (the incident timeline). "Have we hit this before?" lives here.
1303
+ typeName: "postmortem",
1304
+ displayName: "Post-mortem",
1305
+ indexMode: "HYBRID",
1306
+ allowedSurfaces: ["document"],
1307
+ // Intrinsic title + body; schema = metadata beyond those (no typed `title`).
1308
+ fields: [
1309
+ {
1310
+ fieldId: "summary",
1311
+ fieldType: "string",
1312
+ searchable: true,
1313
+ description: "What happened, in brief. The full analysis (impact/root cause/resolution/lesson) is the body.",
1314
+ renderHints: { label: "Summary", widget: "textarea", order: 2 }
1315
+ },
1316
+ {
1317
+ fieldId: "severity",
1318
+ fieldType: "enum",
1319
+ filterable: true,
1320
+ enumValues: ["low", "medium", "high", "critical"],
1321
+ renderHints: { label: "Severity", widget: "select", order: 3 }
1322
+ },
1323
+ {
1324
+ fieldId: "status",
1325
+ fieldType: "enum",
1326
+ filterable: true,
1327
+ enumValues: ["open", "mitigated", "resolved"],
1328
+ renderHints: { label: "Status", widget: "select", order: 4 }
1329
+ },
1330
+ {
1331
+ fieldId: "area",
1332
+ fieldType: "string",
1333
+ filterable: true,
1334
+ renderHints: { label: "Area", widget: "text", order: 5 }
1335
+ },
1336
+ {
1337
+ fieldId: "tags",
1338
+ fieldType: "array",
1339
+ filterable: true,
1340
+ renderHints: { label: "Tags", order: 6 }
1341
+ },
1342
+ {
1343
+ fieldId: "relatedDecision",
1344
+ fieldType: "reference",
1345
+ targetTypeName: "decision",
1346
+ targetSurface: "document",
1347
+ targetField: "externalId",
1348
+ cardinality: "one",
1349
+ description: "A decision implicated in or addressed by this incident (by externalId).",
1350
+ renderHints: { label: "Related decision", order: 7 }
1351
+ },
1352
+ {
1353
+ fieldId: "occurredOn",
1354
+ fieldType: "date",
1355
+ description: 'ISO-8601 \u2014 when it happened. Range-queryable \u2014 "incidents this month".',
1356
+ renderHints: { label: "Occurred on", widget: "date", order: 8 }
1357
+ }
1358
+ ],
1359
+ lookupFields: ["severity", "status", "area", "relatedDecision", { fieldName: "occurredOn", rangeEnabled: true }]
1360
+ },
1361
+ // ============================= RECORDS =============================
1362
+ // Structure-dominant: the typed fields are the artifact. Short, exact-queryable.
1363
+ {
1364
+ // A governance CONTROL — a policy/standard/control the codebase must satisfy,
1365
+ // WITH its evidence. The compliance instrument: it records what enforces it
1366
+ // (`evidence`), the runbook that VERIFIES it (cross-surface → document), and
1367
+ // the decision that mandates it. "Which critical controls are active, and how
1368
+ // is each proven?"
1369
+ typeName: "control",
1370
+ displayName: "Control",
1371
+ indexMode: "HYBRID",
1372
+ fields: [
1373
+ {
1374
+ fieldId: "title",
1375
+ fieldType: "string",
1376
+ required: true,
1377
+ searchable: true,
1378
+ validation: { minLength: 1, maxLength: 200 },
1379
+ renderHints: { label: "Title", widget: "text", order: 1, displayField: true }
1380
+ },
1381
+ {
1382
+ fieldId: "statement",
1383
+ fieldType: "string",
1384
+ searchable: true,
1385
+ description: "The requirement \u2014 what must always hold.",
1386
+ renderHints: { label: "Statement", widget: "textarea", order: 2 }
1387
+ },
1388
+ {
1389
+ fieldId: "rationale",
1390
+ fieldType: "string",
1391
+ searchable: true,
1392
+ description: "Why the control exists \u2014 the risk it prevents.",
1393
+ renderHints: { label: "Rationale", widget: "textarea", order: 3 }
1394
+ },
1395
+ {
1396
+ // The policy → implementation spectrum in one filterable field.
1397
+ fieldId: "kind",
1398
+ fieldType: "enum",
1399
+ filterable: true,
1400
+ enumValues: ["policy", "standard", "control"],
1401
+ renderHints: { label: "Kind", widget: "select", order: 4 }
1402
+ },
1403
+ {
1404
+ // Ordinal, but EQUALITY (range/prefix order is lexical, so low<critical
1405
+ // would sort alphabetically). Enumerate "all critical controls" by equality.
1406
+ fieldId: "criticality",
1407
+ fieldType: "enum",
1408
+ filterable: true,
1409
+ enumValues: ["low", "medium", "high", "critical"],
1410
+ renderHints: { label: "Criticality", widget: "select", order: 5 }
1411
+ },
1412
+ {
1413
+ fieldId: "evidence",
1414
+ fieldType: "string",
1415
+ searchable: true,
1416
+ description: "What enforces or proves the control inline (e.g. an architecture test or gate).",
1417
+ renderHints: { label: "Evidence", widget: "textarea", order: 6 }
1418
+ },
1419
+ {
1420
+ fieldId: "status",
1421
+ fieldType: "enum",
1422
+ filterable: true,
1423
+ enumValues: ["draft", "active", "retired"],
1424
+ renderHints: { label: "Status", widget: "select", order: 7 }
1425
+ },
1426
+ {
1427
+ fieldId: "area",
1428
+ fieldType: "string",
1429
+ filterable: true,
1430
+ renderHints: { label: "Area", widget: "text", order: 8 }
1431
+ },
1432
+ {
1433
+ fieldId: "tags",
1434
+ fieldType: "array",
1435
+ filterable: true,
1436
+ renderHints: { label: "Tags", order: 9 }
1437
+ },
1438
+ {
1439
+ // Cross-surface edge (record → document): the runbook that proves the control.
1440
+ fieldId: "verifiedBy",
1441
+ fieldType: "reference",
1442
+ targetTypeName: "runbook",
1443
+ targetSurface: "document",
1444
+ targetField: "externalId",
1445
+ cardinality: "one",
1446
+ description: "The runbook that verifies this control (by externalId).",
1447
+ renderHints: { label: "Verified by (runbook)", order: 10 }
1448
+ },
1449
+ {
1450
+ // Cross-surface edge (record → document): the decision that mandates it.
1451
+ fieldId: "relatedDecision",
1452
+ fieldType: "reference",
1453
+ targetTypeName: "decision",
1454
+ targetSurface: "document",
1455
+ targetField: "externalId",
1456
+ cardinality: "one",
1457
+ description: "The decision that mandates this control (by externalId).",
1458
+ renderHints: { label: "Related decision", order: 11 }
1459
+ },
1460
+ {
1461
+ fieldId: "reviewedOn",
1462
+ fieldType: "date",
1463
+ description: "ISO-8601 last-reviewed date. Range-queryable.",
1464
+ renderHints: { label: "Reviewed on", widget: "date", order: 12 }
1465
+ }
1466
+ ],
1467
+ lookupFields: [
1468
+ "kind",
1469
+ "criticality",
1470
+ "status",
1471
+ "area",
1472
+ "verifiedBy",
1473
+ "relatedDecision",
1474
+ { fieldName: "reviewedOn", rangeEnabled: true }
1475
+ ]
1476
+ },
1477
+ {
1478
+ // A CONVENTION — a must-follow operating rule the team teaches its agents. The
1479
+ // durable, shareable operating-memory. Distinct fields capture how we actually
1480
+ // write these: the `rule` (imperative), the `why` (rationale), and `howToApply`
1481
+ // (the concrete application) are SEPARATE fields, not one blob — so an agent can
1482
+ // recall the rule, the reasoning, and the how independently.
1483
+ typeName: "convention",
1484
+ displayName: "Convention",
1485
+ indexMode: "HYBRID",
1486
+ fields: [
1487
+ {
1488
+ fieldId: "title",
1489
+ fieldType: "string",
1490
+ required: true,
1491
+ searchable: true,
1492
+ validation: { minLength: 1, maxLength: 200 },
1493
+ renderHints: { label: "Title", widget: "text", order: 1, displayField: true }
1494
+ },
1495
+ {
1496
+ fieldId: "rule",
1497
+ fieldType: "string",
1498
+ searchable: true,
1499
+ description: "The convention itself, stated as an imperative.",
1500
+ renderHints: { label: "Rule", widget: "textarea", order: 2 }
1501
+ },
1502
+ {
1503
+ fieldId: "why",
1504
+ fieldType: "string",
1505
+ searchable: true,
1506
+ description: "Why it matters \u2014 the trade-off / the antipattern it prevents.",
1507
+ renderHints: { label: "Why", widget: "textarea", order: 3 }
1508
+ },
1509
+ {
1510
+ fieldId: "howToApply",
1511
+ fieldType: "string",
1512
+ searchable: true,
1513
+ description: "How to comply in practice \u2014 the concrete application steps.",
1514
+ renderHints: { label: "How to apply", widget: "textarea", order: 4 }
1515
+ },
1516
+ {
1517
+ fieldId: "area",
1518
+ fieldType: "string",
1519
+ filterable: true,
1520
+ renderHints: { label: "Area", widget: "text", order: 5 }
1521
+ },
1522
+ {
1523
+ fieldId: "status",
1524
+ fieldType: "enum",
1525
+ filterable: true,
1526
+ enumValues: ["active", "retired"],
1527
+ renderHints: { label: "Status", widget: "select", order: 6 }
1528
+ },
1529
+ {
1530
+ fieldId: "tags",
1531
+ fieldType: "array",
1532
+ filterable: true,
1533
+ renderHints: { label: "Tags", order: 7 }
1534
+ },
1535
+ {
1536
+ // Cross-surface edge (record → document): the decision that established it.
1537
+ fieldId: "establishedBy",
1538
+ fieldType: "reference",
1539
+ targetTypeName: "decision",
1540
+ targetSurface: "document",
1541
+ targetField: "externalId",
1542
+ cardinality: "one",
1543
+ description: "The decision that established this convention (by externalId).",
1544
+ renderHints: { label: "Established by (decision)", order: 8 }
1545
+ },
1546
+ {
1547
+ fieldId: "updatedOn",
1548
+ fieldType: "date",
1549
+ description: "ISO-8601 \u2014 when last revised. Range-queryable.",
1550
+ renderHints: { label: "Updated on", widget: "date", order: 9 }
1551
+ }
1552
+ ],
1553
+ lookupFields: ["area", "status", "establishedBy", { fieldName: "updatedOn", rangeEnabled: true }]
1554
+ },
1555
+ {
1556
+ // A GOTCHA / sharp edge: a symptom, its cause, and the fix. A tight typed
1557
+ // triple — found by meaning (semantic search on the symptom) + area/status.
1558
+ // The most standalone type; no typed edge.
1559
+ typeName: "gotcha",
1560
+ displayName: "Gotcha",
1561
+ indexMode: "HYBRID",
1562
+ fields: [
1563
+ {
1564
+ fieldId: "symptom",
1565
+ fieldType: "string",
1566
+ required: true,
1567
+ searchable: true,
1568
+ validation: { minLength: 1, maxLength: 500 },
1569
+ renderHints: { label: "Symptom", widget: "textarea", order: 1, displayField: true }
1570
+ },
1571
+ {
1572
+ fieldId: "cause",
1573
+ fieldType: "string",
1574
+ searchable: true,
1575
+ renderHints: { label: "Cause", widget: "textarea", order: 2 }
1576
+ },
1577
+ {
1578
+ fieldId: "fix",
1579
+ fieldType: "string",
1580
+ searchable: true,
1581
+ renderHints: { label: "Fix", widget: "textarea", order: 3 }
1582
+ },
1583
+ {
1584
+ fieldId: "area",
1585
+ fieldType: "string",
1586
+ filterable: true,
1587
+ renderHints: { label: "Area", widget: "text", order: 4 }
1588
+ },
1589
+ {
1590
+ fieldId: "status",
1591
+ fieldType: "enum",
1592
+ filterable: true,
1593
+ enumValues: ["active", "resolved"],
1594
+ renderHints: { label: "Status", widget: "select", order: 5 }
1595
+ },
1596
+ {
1597
+ fieldId: "tags",
1598
+ fieldType: "array",
1599
+ filterable: true,
1600
+ renderHints: { label: "Tags", order: 6 }
1601
+ },
1602
+ {
1603
+ fieldId: "discoveredOn",
1604
+ fieldType: "date",
1605
+ description: "ISO-8601 \u2014 when first hit. Range-queryable.",
1606
+ renderHints: { label: "Discovered on", widget: "date", order: 7 }
1607
+ }
1608
+ ],
1609
+ lookupFields: ["area", "status", { fieldName: "discoveredOn", rangeEnabled: true }]
1610
+ },
1611
+ {
1612
+ // A glossary TERM — a definition keyed by the term itself. Structure-dominant:
1613
+ // `term` is a UNIQUE exact-lookup key (the showcase of a uniqueness constraint),
1614
+ // `definition` is the RAG body, `aliases` catch alternate names. Links to the
1615
+ // decision that defines/establishes the concept where there is one.
1616
+ typeName: "term",
1617
+ displayName: "Glossary term",
1618
+ indexMode: "HYBRID",
1619
+ fields: [
1620
+ {
1621
+ fieldId: "term",
1622
+ fieldType: "string",
1623
+ required: true,
1624
+ searchable: true,
1625
+ validation: { minLength: 1, maxLength: 200 },
1626
+ renderHints: { label: "Term", widget: "text", order: 1, displayField: true }
1627
+ },
1628
+ {
1629
+ fieldId: "definition",
1630
+ fieldType: "string",
1631
+ searchable: true,
1632
+ description: "What the term means \u2014 the RAG-able body.",
1633
+ renderHints: { label: "Definition", widget: "textarea", order: 2 }
1634
+ },
1635
+ {
1636
+ fieldId: "aliases",
1637
+ fieldType: "array",
1638
+ filterable: true,
1639
+ description: "Alternate names / abbreviations for the same concept.",
1640
+ renderHints: { label: "Aliases", order: 3 }
1641
+ },
1642
+ {
1643
+ fieldId: "area",
1644
+ fieldType: "string",
1645
+ filterable: true,
1646
+ renderHints: { label: "Area", widget: "text", order: 4 }
1647
+ },
1648
+ {
1649
+ fieldId: "tags",
1650
+ fieldType: "array",
1651
+ filterable: true,
1652
+ renderHints: { label: "Tags", order: 5 }
1653
+ },
1654
+ {
1655
+ fieldId: "relatedDecision",
1656
+ fieldType: "reference",
1657
+ targetTypeName: "decision",
1658
+ targetSurface: "document",
1659
+ targetField: "externalId",
1660
+ cardinality: "one",
1661
+ description: "A decision that defines or establishes this term (by externalId).",
1662
+ renderHints: { label: "Related decision", order: 6 }
1663
+ },
1664
+ {
1665
+ fieldId: "updatedOn",
1666
+ fieldType: "date",
1667
+ description: "ISO-8601 \u2014 when last revised. Range-queryable.",
1668
+ renderHints: { label: "Updated on", widget: "date", order: 7 }
1669
+ }
1670
+ ],
1671
+ // `term` is a UNIQUE equality lookup — exact "define X" + a one-per-term
1672
+ // guarantee. `area`/`relatedDecision` enumerate; `updatedOn` is the range row.
1673
+ lookupFields: [
1674
+ { fieldName: "term", unique: true },
1675
+ "area",
1676
+ "relatedDecision",
1677
+ { fieldName: "updatedOn", rangeEnabled: true }
1678
+ ]
1679
+ }
1680
+ ],
1681
+ // Least-privilege, data-plane only. r/c/u records + search + schema discovery +
1682
+ // inference:r (grounded recall over the document bodies) + document/folder r/c
1683
+ // (the content artifacts are documents). NO :d — knowledge is superseded/retired
1684
+ // via a status flip, so the trail of how the team's thinking evolved stays intact.
1685
+ accessProfile: {
1686
+ allowedActions: [
1687
+ "records:r",
1688
+ "records:c",
1689
+ "records:u",
1690
+ "search:r",
1691
+ "schemas:r",
1692
+ "inference:r",
1693
+ "documents:r",
1694
+ "documents:c",
1695
+ "folders:r",
1696
+ "folders:c"
1697
+ ]
1698
+ },
1699
+ servicePrincipal: {
1700
+ externalId: "agentic-sdlc",
1701
+ displayName: "Agentic SDLC Knowledge Base"
1702
+ }
1703
+ // No bundled seed in this version: the content artifacts live on the document
1704
+ // surface and the cross-surface graph is populated by the ingest agent
1705
+ // (document_ingest / record_create), not the bootstrap seed step. Production
1706
+ // contexts provision with `vectros bootstrap --no-seed` regardless.
1707
+ };
1708
+ var agentic_sdlc_default = agenticSdlc;
1709
+
981
1710
  // src/blueprints/second-brain.ts
982
1711
  var secondBrain = {
983
1712
  name: "second-brain",
@@ -1074,6 +1803,7 @@ var secondBrain = {
1074
1803
  },
1075
1804
  seed: [
1076
1805
  {
1806
+ surface: "record",
1077
1807
  typeName: "note",
1078
1808
  externalId: "seed-welcome",
1079
1809
  fields: {
@@ -1207,6 +1937,7 @@ var clinicalIntake = {
1207
1937
  },
1208
1938
  seed: [
1209
1939
  {
1940
+ surface: "record",
1210
1941
  typeName: "intake",
1211
1942
  externalId: "seed-synthetic-intake",
1212
1943
  fields: {
@@ -1230,6 +1961,7 @@ var clinical_intake_default = clinicalIntake;
1230
1961
  var BUNDLED_BLUEPRINTS = [
1231
1962
  task_management_default,
1232
1963
  coding_agent_memory_default,
1964
+ agentic_sdlc_default,
1233
1965
  second_brain_default,
1234
1966
  clinical_intake_default
1235
1967
  ];