@archinsight/cli 3.0.0-snapshot.5 → 3.0.0-snapshot.7

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.
Files changed (3) hide show
  1. package/README.md +9 -1
  2. package/build/index.js +1040 -100
  3. package/package.json +1 -1
package/build/index.js CHANGED
@@ -57,7 +57,7 @@ var require_archy = __commonJS({
57
57
 
58
58
  // src/index.ts
59
59
  var import_archy = __toESM(require_archy(), 1);
60
- import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
60
+ import { mkdir, readdir, readFile, rm, stat, writeFile } from "node:fs/promises";
61
61
  import path from "node:path";
62
62
  import { instance } from "@viz-js/viz";
63
63
 
@@ -34184,6 +34184,7 @@ function linkProject(request) {
34184
34184
  sourceIdentity: edge.sourceName,
34185
34185
  fromId: edge.source,
34186
34186
  toId: target.id,
34187
+ projectedAttributes: materialized.edge.attributes,
34187
34188
  ...materialized.edge.annotations === void 0 ? {} : { annotations: materialized.edge.annotations }
34188
34189
  });
34189
34190
  pendingProjections.push({
@@ -34191,6 +34192,7 @@ function linkProject(request) {
34191
34192
  fromId: edge.source,
34192
34193
  toId: target.id,
34193
34194
  attributes: edgeAttributes,
34195
+ projectedAttributes: materialized.edge.attributes,
34194
34196
  ...materialized.edge.annotations === void 0 ? {} : { annotations: materialized.edge.annotations }
34195
34197
  });
34196
34198
  }
@@ -34220,7 +34222,7 @@ function linkProject(request) {
34220
34222
  });
34221
34223
  }
34222
34224
  for (const projection of pendingProjections) {
34223
- addProjectedEdges(linkedEdges, projection.sourceIdentity, projection.fromId, projection.toId, projection.attributes, linkedElementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, void 0, projection.annotations);
34225
+ addProjectedEdges(linkedEdges, projection.sourceIdentity, projection.fromId, projection.toId, projection.attributes, linkedElementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, void 0, projection.annotations, projection.projectedAttributes);
34224
34226
  }
34225
34227
  const slotDomainTypes = typeSystem.slotDomainTypes();
34226
34228
  for (const element of elements) {
@@ -35248,7 +35250,14 @@ function resolveAttributes(owner, ownerType, attributes2, referenceAttributePosi
35248
35250
  });
35249
35251
  continue;
35250
35252
  }
35251
- result[name] = [...result[name] ?? [], { id: resolved.id, element: resolved }];
35253
+ result[name] = [...result[name] ?? [], {
35254
+ id: resolved.id,
35255
+ element: resolved,
35256
+ line: value.line,
35257
+ column: value.column,
35258
+ ...value.endLine === void 0 ? {} : { endLine: value.endLine },
35259
+ ...value.endColumn === void 0 ? {} : { endColumn: value.endColumn }
35260
+ }];
35252
35261
  }
35253
35262
  }
35254
35263
  return result;
@@ -35284,7 +35293,7 @@ function flattenAttributes(scalarAttributes, attributes2) {
35284
35293
  ...Object.fromEntries(Object.entries(attributes2).map(([name, values]) => [name, values.map((value) => value.id)]))
35285
35294
  };
35286
35295
  }
35287
- function addProjectedEdges(linkedEdges, sourceIdentity, fromId, toId, attributes2, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = [], visitedProjectionElements = /* @__PURE__ */ new Set()) {
35296
+ function addProjectedEdges(linkedEdges, sourceIdentity, fromId, toId, attributes2, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = [], projectedAttributes, visitedProjectionElements = /* @__PURE__ */ new Set()) {
35288
35297
  for (const values of Object.values(attributes2)) {
35289
35298
  for (const value of values) {
35290
35299
  if (value.element === void 0) {
@@ -35301,8 +35310,24 @@ function addProjectedEdges(linkedEdges, sourceIdentity, fromId, toId, attributes
35301
35310
  if (isDirectSlotReferenceSelfProjection(value.element, fromId, toId)) {
35302
35311
  continue;
35303
35312
  }
35304
- for (const rule3 of typeSystem.projectionRules(value.element.type)) {
35305
- addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, value.element, rule3, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2);
35313
+ const rules = typeSystem.projectionRules(value.element.type);
35314
+ if (fromId === toId && rules.some(projectionRuleUsesTo)) {
35315
+ const position3 = value.line === void 0 || value.column === void 0 ? value.element : {
35316
+ line: value.line,
35317
+ column: value.column,
35318
+ ...value.endLine === void 0 ? {} : { endLine: value.endLine },
35319
+ ...value.endColumn === void 0 ? {} : { endColumn: value.endColumn }
35320
+ };
35321
+ diagnostics.push({
35322
+ code: "PROJECTION_TARGET_REQUIRED",
35323
+ message: `Projection for '${value.element.type}' uses '$to' and must be attached to a relationship, not to element '${fromId}'`,
35324
+ sourceName: sourceIdentity,
35325
+ ...diagnosticPosition2(position3)
35326
+ });
35327
+ continue;
35328
+ }
35329
+ for (const rule3 of rules) {
35330
+ addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, value.element, rule3, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2, projectedAttributes);
35306
35331
  }
35307
35332
  addProjectedEdges(
35308
35333
  linkedEdges,
@@ -35317,12 +35342,13 @@ function addProjectedEdges(linkedEdges, sourceIdentity, fromId, toId, attributes
35317
35342
  diagnostics,
35318
35343
  projectionScope,
35319
35344
  annotations2,
35345
+ void 0,
35320
35346
  visitedProjectionElements
35321
35347
  );
35322
35348
  }
35323
35349
  }
35324
35350
  }
35325
- function addProjectedEdgesForValues(linkedEdges, sourceIdentity, fromId, toId, values, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = []) {
35351
+ function addProjectedEdgesForValues(linkedEdges, sourceIdentity, fromId, toId, values, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = [], projectedAttributes) {
35326
35352
  addProjectedEdges(
35327
35353
  linkedEdges,
35328
35354
  sourceIdentity,
@@ -35335,7 +35361,8 @@ function addProjectedEdgesForValues(linkedEdges, sourceIdentity, fromId, toId, v
35335
35361
  typeSystem,
35336
35362
  diagnostics,
35337
35363
  projectionScope,
35338
- annotations2
35364
+ annotations2,
35365
+ projectedAttributes
35339
35366
  );
35340
35367
  }
35341
35368
  function addEdgeScopes(scopesByCarrierId, attributes2, scope) {
@@ -35352,15 +35379,16 @@ function addEdgeScopes(scopesByCarrierId, attributes2, scope) {
35352
35379
  function isDirectSlotReferenceSelfProjection(element, fromId, toId) {
35353
35380
  return fromId === toId && element.parent === fromId && element.scalarAttributes.parentType !== void 0 && element.scalarAttributes.attributeName !== void 0;
35354
35381
  }
35355
- function addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, projectionElement, rule3, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = []) {
35382
+ function addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, projectionElement, rule3, elementsById, resolvedElementAttributes, ownerIndependentProjectionKeys, typeSystem, diagnostics, projectionScope, annotations2 = [], projectedAttributes) {
35356
35383
  const sources = projectionTerm(rule3.source, fromId, toId, projectionElement, elementsById, resolvedElementAttributes, diagnostics);
35357
35384
  const targets = projectionTerm(rule3.target, fromId, toId, projectionElement, elementsById, resolvedElementAttributes, diagnostics);
35385
+ const carriedAttributes = rule3.source.kind === "from" ? projectedAttributes : void 0;
35358
35386
  for (const source of sources) {
35359
35387
  for (const target of targets) {
35360
35388
  if (!projectionRuleUsesOwner(rule3)) {
35361
35389
  const key = `${projectionElement.id}\0${source}\0${rule3.operator}\0${target}`;
35362
35390
  if (ownerIndependentProjectionKeys.has(key)) {
35363
- mergeProjectedEdgeAnnotations(linkedEdges, source, rule3.operator, target, annotations2);
35391
+ mergeProjectedEdge(linkedEdges, source, rule3.operator, target, annotations2, carriedAttributes);
35364
35392
  continue;
35365
35393
  }
35366
35394
  ownerIndependentProjectionKeys.add(key);
@@ -35375,6 +35403,7 @@ function addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, project
35375
35403
  if (edge !== void 0) {
35376
35404
  linkedEdges[existingIndex] = {
35377
35405
  ...edge,
35406
+ attributes: mergeAttributeValues(carriedAttributes, edge.attributes),
35378
35407
  annotations: uniqueAnnotations([...edge.annotations ?? [], ...annotations2])
35379
35408
  };
35380
35409
  }
@@ -35388,7 +35417,7 @@ function addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, project
35388
35417
  operator: rule3.operator,
35389
35418
  type,
35390
35419
  sourceIdentity,
35391
- attributes: {},
35420
+ attributes: carriedAttributes ?? {},
35392
35421
  ...listAttributesProperty(typeSystem, type),
35393
35422
  projected: true,
35394
35423
  ...projectionScope === void 0 ? {} : { projectionScope },
@@ -35397,8 +35426,8 @@ function addProjectedRuleEdge(linkedEdges, sourceIdentity, fromId, toId, project
35397
35426
  }
35398
35427
  }
35399
35428
  }
35400
- function mergeProjectedEdgeAnnotations(linkedEdges, source, operator, target, annotations2) {
35401
- if (annotations2.length === 0) {
35429
+ function mergeProjectedEdge(linkedEdges, source, operator, target, annotations2, attributes2) {
35430
+ if (annotations2.length === 0 && (attributes2 === void 0 || Object.keys(attributes2).length === 0)) {
35402
35431
  return;
35403
35432
  }
35404
35433
  const index = linkedEdges.findIndex((edge2) => edge2.projected === true && edge2.source === source && edge2.operator === operator && edge2.target === target);
@@ -35411,9 +35440,19 @@ function mergeProjectedEdgeAnnotations(linkedEdges, source, operator, target, an
35411
35440
  }
35412
35441
  linkedEdges[index] = {
35413
35442
  ...edge,
35443
+ attributes: mergeAttributeValues(attributes2, edge.attributes),
35414
35444
  annotations: uniqueAnnotations([...edge.annotations ?? [], ...annotations2])
35415
35445
  };
35416
35446
  }
35447
+ function mergeAttributeValues(base, override) {
35448
+ if (base === void 0 || Object.keys(base).length === 0) {
35449
+ return override;
35450
+ }
35451
+ if (Object.keys(override).length === 0) {
35452
+ return base;
35453
+ }
35454
+ return { ...base, ...override };
35455
+ }
35417
35456
  function uniqueAnnotations(annotations2) {
35418
35457
  const seen = /* @__PURE__ */ new Set();
35419
35458
  const result = [];
@@ -35438,6 +35477,12 @@ function referenceAttributesProperty(attributes2) {
35438
35477
  function projectionRuleUsesOwner(rule3) {
35439
35478
  return projectionTermUsesOwner(rule3.source) || projectionTermUsesOwner(rule3.target);
35440
35479
  }
35480
+ function projectionRuleUsesTo(rule3) {
35481
+ return projectionTermUsesTo(rule3.source) || projectionTermUsesTo(rule3.target);
35482
+ }
35483
+ function projectionTermUsesTo(term) {
35484
+ return term.kind === "to";
35485
+ }
35441
35486
  function projectionTermUsesOwner(term) {
35442
35487
  return term.kind === "from" || term.kind === "to" || term.kind === "slot";
35443
35488
  }
@@ -36029,7 +36074,8 @@ function applyDeploymentUsesCarrier(carrier, parent, context) {
36029
36074
  context.typeSystem,
36030
36075
  context.diagnostics,
36031
36076
  projectionScope,
36032
- annotations2
36077
+ annotations2,
36078
+ scope.projectedAttributes
36033
36079
  );
36034
36080
  }
36035
36081
  }
@@ -37802,7 +37848,7 @@ var QueryParser = class {
37802
37848
  };
37803
37849
 
37804
37850
  // src/version.ts
37805
- var version = "3.0.0-snapshot.5";
37851
+ var version = "3.0.0-snapshot.7";
37806
37852
 
37807
37853
  // src/index.ts
37808
37854
  var hiddenStructureTypes = /* @__PURE__ */ new Set(["List", "Nothing", "Text", "text"]);
@@ -37995,11 +38041,24 @@ async function runSkillInit(args, skillPackage) {
37995
38041
  const projectRoot = path.resolve(projectPath(args));
37996
38042
  const usesDefaultOutput = args.output === void 0;
37997
38043
  const outputRoot = path.resolve(projectRoot, args.output ?? skillPackage.defaultOutput);
38044
+ if (args.force && await exists(outputRoot)) {
38045
+ assertSafeSkillOutputRoot(projectRoot, outputRoot);
38046
+ await rm(outputRoot, { recursive: true, force: true });
38047
+ }
37998
38048
  for (const file of skillPackage.files) {
37999
38049
  await writeGeneratedFile(path.join(outputRoot, file.path), file.content, args.force);
38000
38050
  }
38001
38051
  process.stdout.write(skillPackageSuccess(projectRoot, outputRoot, skillPackage, usesDefaultOutput));
38002
38052
  }
38053
+ function assertSafeSkillOutputRoot(projectRoot, outputRoot) {
38054
+ if (outputRoot === path.parse(outputRoot).root || outputRoot === process.cwd() || outputRoot === projectRoot) {
38055
+ throw new CliError(`Refusing to delete unsafe skill output directory '${outputRoot}'. Choose a dedicated --out directory.`);
38056
+ }
38057
+ const projectRelativeToOutput = path.relative(outputRoot, projectRoot);
38058
+ if (projectRelativeToOutput !== "" && !projectRelativeToOutput.startsWith("..") && !path.isAbsolute(projectRelativeToOutput)) {
38059
+ throw new CliError(`Refusing to delete skill output directory '${outputRoot}' because it contains the project root.`);
38060
+ }
38061
+ }
38003
38062
  async function loadProject(input) {
38004
38063
  const root = path.resolve(input);
38005
38064
  const sources = await readSources(root);
@@ -38452,7 +38511,7 @@ Options:
38452
38511
  -o, --out <file> Write output to file instead of stdout; for skill init, write the guide directory.
38453
38512
  -t, --theme <theme> Render theme, default: light.
38454
38513
  --target <target> Skill target: generic, codex, or claude.
38455
- --force Replace existing generated skill files.
38514
+ --force Delete and recreate the generated skill directory.
38456
38515
  -V, --version Print version.
38457
38516
  -h, --help Show help.
38458
38517
 
@@ -38539,6 +38598,10 @@ function sharedSkillFiles() {
38539
38598
  path: "references/c4-deployment.md",
38540
38599
  content: genericC4DeploymentReference()
38541
38600
  },
38601
+ {
38602
+ path: "references/scaling.md",
38603
+ content: genericScalingReference()
38604
+ },
38542
38605
  {
38543
38606
  path: "references/project-structure.md",
38544
38607
  content: genericProjectStructureReference()
@@ -38555,6 +38618,10 @@ function sharedSkillFiles() {
38555
38618
  path: "references/queries.md",
38556
38619
  content: genericQueriesReference()
38557
38620
  },
38621
+ {
38622
+ path: "references/query-recipes.md",
38623
+ content: genericQueryRecipesReference()
38624
+ },
38558
38625
  {
38559
38626
  path: "examples/layered-architecture.ai",
38560
38627
  content: genericLayeredArchitectureExample()
@@ -38583,6 +38650,26 @@ function sharedSkillFiles() {
38583
38650
  path: "examples/c2-containers.aiq",
38584
38651
  content: genericC2QueryExample()
38585
38652
  },
38653
+ {
38654
+ path: "examples/builtin-views/no-filter.aiq",
38655
+ content: noFilterQuery
38656
+ },
38657
+ {
38658
+ path: "examples/builtin-views/c1.aiq",
38659
+ content: c1Query
38660
+ },
38661
+ {
38662
+ path: "examples/builtin-views/c2.aiq",
38663
+ content: c2Query
38664
+ },
38665
+ {
38666
+ path: "examples/builtin-views/c3.aiq",
38667
+ content: c3Query
38668
+ },
38669
+ {
38670
+ path: "examples/builtin-views/c4.aiq",
38671
+ content: c4Query
38672
+ },
38586
38673
  ...coreSkillFiles()
38587
38674
  ];
38588
38675
  }
@@ -38645,8 +38732,18 @@ If \`archinsight\` is not available, ask the user to install or expose
38645
38732
  2. Preserve indentation and the project's existing naming style.
38646
38733
  3. Model architecture from the outside inward: context, external actors/systems,
38647
38734
  systems, containers/services, components, and deployment details.
38648
- 4. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38649
- 5. Validate every Insight change with \`archinsight link . --format text\`.
38735
+ 4. Do not ask about deployment depth until the task touches infrastructure,
38736
+ runtime placement, regions, brokers, gateways, storage, or deployment.
38737
+ 5. At that point, decide per system whether pragmatic mixed C2 or clean
38738
+ C4/deployment is appropriate. If modeling clean C4: attach placement/storage
38739
+ to elements, attach path infrastructure that needs \`$to\` to wires, and make
38740
+ pub/sub dependencies consumer-owned.
38741
+ 6. If a diagram becomes noisy, adjust scope/query before changing a correct
38742
+ graph model.
38743
+ 7. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38744
+ 8. Keep definition/framework files separate from model files that declare
38745
+ \`context <id>\`.
38746
+ 9. Validate every Insight change with \`archinsight link . --format text\`.
38650
38747
 
38651
38748
  ## References
38652
38749
 
@@ -38664,12 +38761,16 @@ If \`archinsight\` is not available, ask the user to install or expose
38664
38761
  - Read \`references/c4-deployment.md\` when adding or repairing deployment/C4
38665
38762
  models, infrastructure inventories, environment-scoped infrastructure, or
38666
38763
  projection rules.
38764
+ - Read \`references/scaling.md\` when splitting a repository into reusable
38765
+ framework, environment, profile, system, or deployment-view files.
38667
38766
  - Read \`references/project-structure.md\` before searching for declarations,
38668
38767
  planning imports, or making broad edits.
38669
38768
  - Read \`references/core.md\` and \`.core/*.ai\` when checking built-in types,
38670
38769
  attributes, presentations, or projections.
38671
38770
  - Read \`references/queries.md\` when writing custom diagram queries or \`.aiq\`
38672
38771
  files.
38772
+ - Read \`references/query-recipes.md\` when a built-in view hides an expected
38773
+ element/edge or needs customization.
38673
38774
  - Read \`references/validation.md\` before running checks, structure inspection,
38674
38775
  or rendering.
38675
38776
  - Use \`examples/layered-architecture.ai\` as a compact valid model.
@@ -38706,12 +38807,16 @@ Treat this \`SKILL.md\` as the entrypoint. Load reference files only when needed
38706
38807
  - Read \`references/c4-deployment.md\` before adding or repairing deployment/C4
38707
38808
  models, infrastructure inventories, environment-scoped infrastructure, or
38708
38809
  projection rules.
38810
+ - Read \`references/scaling.md\` before splitting a repository into reusable
38811
+ framework, environment, profile, system, or deployment-view files.
38709
38812
  - Read \`references/project-structure.md\` before searching for declarations,
38710
38813
  planning imports, or making broad edits.
38711
38814
  - Read \`references/core.md\` and \`.core/*.ai\` before assuming available
38712
38815
  constructors, attributes, presentations, or projections.
38713
38816
  - Read \`references/queries.md\` before writing custom diagram queries or \`.aiq\`
38714
38817
  files.
38818
+ - Read \`references/query-recipes.md\` before customizing a built-in view or
38819
+ explaining why an expected element/edge is hidden.
38715
38820
  - Read \`references/validation.md\` before running checks, structure inspection,
38716
38821
  or rendering commands.
38717
38822
 
@@ -38738,11 +38843,21 @@ If \`archinsight\` is not available, ask the user to install or expose
38738
38843
  2. Preserve indentation and the project's existing naming style.
38739
38844
  3. Model architecture from the outside inward: context, external actors/systems,
38740
38845
  systems, containers/services, components, and deployment details.
38741
- 4. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38742
- 5. Use \`archinsight structure . --format text\` before broad edits when the
38846
+ 4. Do not ask about deployment depth until the task touches infrastructure,
38847
+ runtime placement, regions, brokers, gateways, storage, or deployment.
38848
+ 5. At that point, decide per system whether pragmatic mixed C2 or clean
38849
+ C4/deployment is appropriate. If modeling clean C4: attach placement/storage
38850
+ to elements, attach path infrastructure that needs \`$to\` to wires, and make
38851
+ pub/sub dependencies consumer-owned.
38852
+ 6. If a diagram becomes noisy, adjust scope/query before changing a correct
38853
+ graph model.
38854
+ 7. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38855
+ 8. Keep definition/framework files separate from model files that declare
38856
+ \`context <id>\`.
38857
+ 9. Use \`archinsight structure . --format text\` before broad edits when the
38743
38858
  project shape is unclear.
38744
- 6. Validate every Insight change with \`archinsight link . --format text\`.
38745
- 7. If validation fails, fix the first real syntax/type/linking error before
38859
+ 10. Validate every Insight change with \`archinsight link . --format text\`.
38860
+ 11. If validation fails, fix the first real syntax/type/linking error before
38746
38861
  adding more model content.
38747
38862
 
38748
38863
  ## References
@@ -38761,12 +38876,16 @@ If \`archinsight\` is not available, ask the user to install or expose
38761
38876
  - Read \`references/c4-deployment.md\` when adding or repairing deployment/C4
38762
38877
  models, infrastructure inventories, environment-scoped infrastructure, or
38763
38878
  projection rules.
38879
+ - Read \`references/scaling.md\` when splitting a repository into reusable
38880
+ framework, environment, profile, system, or deployment-view files.
38764
38881
  - Read \`references/project-structure.md\` before searching for declarations,
38765
38882
  planning imports, or making broad edits.
38766
38883
  - Read \`references/core.md\` and \`.core/*.ai\` when checking built-in types,
38767
38884
  attributes, presentations, or projections.
38768
38885
  - Read \`references/queries.md\` when writing custom diagram queries or \`.aiq\`
38769
38886
  files.
38887
+ - Read \`references/query-recipes.md\` when a built-in view hides an expected
38888
+ element/edge or needs customization.
38770
38889
  - Read \`references/validation.md\` before running checks, structure inspection,
38771
38890
  or rendering.
38772
38891
  - Use \`examples/layered-architecture.ai\` as a compact valid model.
@@ -38804,12 +38923,16 @@ they are needed:
38804
38923
  - Read \`references/c4-deployment.md\` before adding or repairing deployment/C4
38805
38924
  models, infrastructure inventories, environment-scoped infrastructure, or
38806
38925
  projection rules.
38926
+ - Read \`references/scaling.md\` before splitting a repository into reusable
38927
+ framework, environment, profile, system, or deployment-view files.
38807
38928
  - Read \`references/project-structure.md\` before searching for declarations,
38808
38929
  planning imports, or making broad edits.
38809
38930
  - Read \`references/core.md\` and \`.core/*.ai\` before assuming available
38810
38931
  constructors, attributes, presentations, or projections.
38811
38932
  - Read \`references/queries.md\` before writing custom diagram queries or \`.aiq\`
38812
38933
  files.
38934
+ - Read \`references/query-recipes.md\` before customizing a built-in view or
38935
+ explaining why an expected element/edge is hidden.
38813
38936
  - Read \`references/validation.md\` before asking the user to run validation,
38814
38937
  structure inspection, or rendering commands.
38815
38938
 
@@ -38836,12 +38959,22 @@ install or expose \`@archinsight/cli\` before changing \`.ai\` files.
38836
38959
  2. Preserve indentation and the project's existing naming style.
38837
38960
  3. Model architecture from the outside inward: context, external actors/systems,
38838
38961
  systems, containers/services, components, and deployment details.
38839
- 4. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38840
- 5. Use \`archinsight structure . --format text\` to inspect the current model
38962
+ 4. Do not ask about deployment depth until the task touches infrastructure,
38963
+ runtime placement, regions, brokers, gateways, storage, or deployment.
38964
+ 5. At that point, decide per system whether pragmatic mixed C2 or clean
38965
+ C4/deployment is appropriate. If modeling clean C4: attach placement/storage
38966
+ to elements, attach path infrastructure that needs \`$to\` to wires, and make
38967
+ pub/sub dependencies consumer-owned.
38968
+ 6. If a diagram becomes noisy, adjust scope/query before changing a correct
38969
+ graph model.
38970
+ 7. Prefer small, focused files connected by \`context\`, \`import\`, and \`extend\`.
38971
+ 8. Keep definition/framework files separate from model files that declare
38972
+ \`context <id>\`.
38973
+ 9. Use \`archinsight structure . --format text\` to inspect the current model
38841
38974
  before broad edits when the CLI is available.
38842
- 6. Validate every Insight change with \`archinsight link . --format text\` when
38975
+ 10. Validate every Insight change with \`archinsight link . --format text\` when
38843
38976
  shell access is available; otherwise ask the user to run validation.
38844
- 7. If validation fails, fix the first real syntax/type/linking error before
38977
+ 11. If validation fails, fix the first real syntax/type/linking error before
38845
38978
  adding more model content.
38846
38979
 
38847
38980
  ## Communication
@@ -38879,12 +39012,16 @@ sections of Insight unless the existing layering is already understood.
38879
39012
  - Read \`references/c4-deployment.md\` when adding or repairing deployment/C4
38880
39013
  models, infrastructure inventories, environment-scoped infrastructure, or
38881
39014
  projection rules.
39015
+ - Read \`references/scaling.md\` when splitting a repository into reusable
39016
+ framework, environment, profile, system, or deployment-view files.
38882
39017
  - Read \`references/project-structure.md\` before searching for declarations,
38883
39018
  planning imports, or making broad edits.
38884
39019
  - Read \`references/core.md\` and \`.core/*.ai\` when checking built-in types,
38885
39020
  attributes, presentations, or projections.
38886
39021
  - Read \`references/queries.md\` when writing custom diagram queries or \`.aiq\`
38887
39022
  files.
39023
+ - Read \`references/query-recipes.md\` when a built-in view hides an expected
39024
+ element/edge or needs customization.
38888
39025
  - Read \`references/validation.md\` before running checks, structure inspection,
38889
39026
  or rendering.
38890
39027
  - Use \`examples/layered-architecture.ai\` as a compact valid model.
@@ -38906,6 +39043,40 @@ function genericModelingReference() {
38906
39043
  Insight syntax is small; most mistakes are modeling mistakes. Decide the view
38907
39044
  question before changing files.
38908
39045
 
39046
+ ## Separate Definitions From Model Sources
39047
+
39048
+ Keep language/framework definitions separate from graph model files.
39049
+
39050
+ - Definition/framework files contain \`define type\`, \`define operator\`,
39051
+ \`define presentation\`, \`extend type\`, \`extend enum of\`, and
39052
+ \`extend presentation\`.
39053
+ - Model files declare \`context <id>\` and create graph objects with
39054
+ constructors such as \`system\`, \`service\`, \`component\`, \`environment\`,
39055
+ or \`deploymentProfile\`.
39056
+
39057
+ Do not mix definition declarations and \`context\` declarations in one source
39058
+ file. Put shared vocabulary in a framework file, then put concrete contexts,
39059
+ systems, environments, profiles, and links in model files. This keeps schema
39060
+ changes reviewable and avoids source-level syntax failures.
39061
+
39062
+ ## Model Source Granularity
39063
+
39064
+ Default to one primary owned system per model source file: the system you are
39065
+ about to detail with containers, services, components, and deployment
39066
+ relationships. This keeps the selected source file useful as a C2/C3/C4 view
39067
+ scope and avoids accidental mega-files.
39068
+
39069
+ Do not create one file per external actor or external system. Shared external
39070
+ dependencies are usually better modeled once in a reusable external context, or
39071
+ in a few external contexts grouped by meaning such as \`external_platforms\`,
39072
+ \`partners\`, or \`regulators\`. Import those shared declarations from system
39073
+ files that need them.
39074
+
39075
+ If a user asks for deeper splitting, use \`extend <object>\` files for the
39076
+ detail being extracted. For example, keep the main service file readable and put
39077
+ large per-service component sets in a small utility subdirectory for that
39078
+ context.
39079
+
38909
39080
  ## Projections Are Bottom-Up
38910
39081
 
38911
39082
  Built-in C1/C2/C3/C4 views are selected from the linked model. They are not
@@ -38969,23 +39140,50 @@ type hierarchy:
38969
39140
  If a nested declaration fails type checking, fix the type/ownership model rather
38970
39141
  than forcing a link or inventing a wrapper element.
38971
39142
 
38972
- ## Keep Infrastructure in the Right View
39143
+ ## Choose Infrastructure Depth Per System
39144
+
39145
+ Do not force every project into C4/deployment on the first pass. Most modeling
39146
+ work can proceed through C1-C3 without asking about deployment depth. When the
39147
+ task first touches infrastructure, runtime placement, regions, compute, brokers,
39148
+ gateways, storage, or deployment, ask the user or infer from the repository
39149
+ whether the affected system needs a pragmatic mixed C2 view or a clean
39150
+ C4/deployment model.
39151
+
39152
+ Pragmatic mixed C2 is fast: model databases, brokers, gateways, or secret stores
39153
+ next to services when the user wants a quick single-environment diagram. The
39154
+ cost is that C2 now mixes logical containers with infrastructure, and C4 is
39155
+ effectively absent for that system.
38973
39156
 
38974
- Do not transcribe infrastructure into C2 just because another diagram drew it
38975
- there. Databases, queues, secret stores, compute nodes, gateways, and runtime
38976
- placement are usually deployment/C4 concerns unless the project defines them as
38977
- part of the selected view.
39157
+ Clean C4 keeps C2 logical and moves physical realization into deployment
39158
+ profiles, environments, inventory slots, and projection rules. This is more work
39159
+ up front, but it supports many-to-many deployment: one logical service can run
39160
+ in several environments whose infrastructure differs by region, provider, or
39161
+ organizational boundary.
38978
39162
 
38979
- Use deployment types and projection queries when physical realization matters.
39163
+ This choice is per-system, not global. A critical system can use clean C4 while
39164
+ peripheral systems stay pragmatic in C2. Starting cheap is acceptable, but know
39165
+ that upgrading mixed C2 infrastructure into clean C4 is a migration, not just an
39166
+ extra attribute.
38980
39167
 
38981
39168
  ## Eventing
38982
39169
 
38983
39170
  Use \`~>\` for asynchronous relationships. Model one async wire per meaningful
38984
39171
  topic or event flow between real producer and consumer elements.
38985
39172
 
39173
+ For pub/sub, make the dependency consumer-owned:
39174
+
39175
+ - The producer/source declares the event topic as part of its contract, but does
39176
+ not maintain a manual list of subscribers.
39177
+ - The consumer declares \`~> producer\` with \`via = <topic>\`, because the
39178
+ consumer depends on the producer's event contract.
39179
+ - To answer "who depends on this event?", query the graph for incoming async
39180
+ dependencies instead of editing a subscriber list on the producer.
39181
+
38986
39182
  Do not invent a broker node just to make the diagram look familiar. If the
38987
- broker is deployment infrastructure, model it in deployment/C4. If the producer
38988
- or consumer is not known, leave a gap and report it instead of fabricating an
39183
+ chosen style is clean C4 and the broker is deployment infrastructure, model it
39184
+ in deployment/C4. If the chosen style is pragmatic mixed C2, a broker-like node
39185
+ can be acceptable, but document that the view mixes levels. If the producer or
39186
+ consumer is not known, leave a gap and report it instead of fabricating an
38989
39187
  element.
38990
39188
 
38991
39189
  ## No Fabricated Elements
@@ -39069,6 +39267,11 @@ Definition files are different from model files. They declare vocabulary:
39069
39267
  \`extend enum of\`, and \`extend presentation\`. Model files usually start with
39070
39268
  \`context <id>\` and then create graph object instances with constructors.
39071
39269
 
39270
+ Do not mix these source forms in one file. A framework/definitions file should
39271
+ contain only vocabulary/schema declarations. A model file should declare a
39272
+ \`context <id>\` and graph object instances. If both are needed, create two
39273
+ files and validate the whole project.
39274
+
39072
39275
  ## Type Definitions and Extensions
39073
39276
 
39074
39277
  Use \`define type\` to create a new graph/value type. Use \`extend type\` to add
@@ -39126,10 +39329,10 @@ links:
39126
39329
  technology = HTTPS, JSON
39127
39330
  call = POST /checkout
39128
39331
  description = Places an order
39129
- ~> analytics
39332
+ ~> order_events
39130
39333
  technology = Kafka
39131
39334
  via = orders.created
39132
- description = Publishes order events
39335
+ description = Consumes order events
39133
39336
  \`\`\`
39134
39337
 
39135
39338
  \`call\` is singular and belongs to synchronous \`->\` links. \`via\` belongs to
@@ -39179,22 +39382,79 @@ Use \`extend type\` / \`extend presentation\` when patching existing vocabulary.
39179
39382
  Repeating \`define presentation X\` for an existing presentation is a diagnostic
39180
39383
  in current Archinsight.
39181
39384
 
39385
+ ## Comments and Notes
39386
+
39387
+ Use \`#\` for ordinary comments when you want to leave guidance for humans or
39388
+ agents without changing the model:
39389
+
39390
+ \`\`\`insight
39391
+ # This file owns the checkout bounded context.
39392
+ context checkout
39393
+
39394
+ system checkout_platform
39395
+ # Keep logical services here; deployment inventory belongs in C4 files.
39396
+ name = Checkout Platform
39397
+ \`\`\`
39398
+
39399
+ A \`#\` after an element or relationship line is an inline note. Notes are
39400
+ stored in the linked graph and can be rendered as note nodes near the element or
39401
+ edge:
39402
+
39403
+ \`\`\`insight
39404
+ context checkout
39405
+
39406
+ system checkout_platform
39407
+ name = Checkout Platform
39408
+
39409
+ container api # Public API owned by the checkout team
39410
+ name = Checkout API
39411
+ links:
39412
+ -> payment_gateway # PCI-sensitive request path
39413
+ technology = HTTPS
39414
+ call = POST /payments
39415
+
39416
+ external system payment_gateway
39417
+ name = Payment gateway
39418
+ \`\`\`
39419
+
39420
+ Use comments for authoring hints that should stay invisible in diagrams. Use
39421
+ notes for architecture remarks that should travel with the model and help
39422
+ readers understand a specific element or relationship.
39423
+
39182
39424
  ## Annotations
39183
39425
 
39184
- Annotations decorate the next declaration or link:
39426
+ Annotations decorate the next declaration or relationship. Put each annotation
39427
+ on its own line immediately before the target:
39185
39428
 
39186
39429
  \`\`\`insight
39187
- @planned
39188
- external system warehouse
39189
- name = Warehouse
39430
+ context fulfillment
39190
39431
 
39191
- links:
39192
- @deprecated
39193
- ~> legacy_erp
39432
+ system fulfillment_platform
39433
+ name = Fulfillment Platform
39434
+
39435
+ @planned
39436
+ container fulfillment_adapter
39437
+ name = Fulfillment adapter
39438
+ links:
39439
+ @deprecated(replace after ERP migration)
39440
+ ~> legacy_erp # scheduled for removal
39441
+
39442
+ external system legacy_erp
39443
+ name = Legacy ERP
39194
39444
  \`\`\`
39195
39445
 
39196
- Use presentation definitions for durable visual styling. Avoid adding new
39197
- Graphviz attributes directly unless the project already uses that convention.
39446
+ Available annotations:
39447
+
39448
+ - \`@planned\` marks an element or relationship as planned or not fully
39449
+ implemented yet. The default Graphviz renderer highlights it in green.
39450
+ - \`@deprecated\` marks an element or relationship as legacy or scheduled for
39451
+ removal. Add optional text in parentheses when the replacement or reason is
39452
+ useful. The default Graphviz renderer highlights it in red.
39453
+
39454
+ Annotations can be stacked and are preserved on projected relationships, so a
39455
+ C4 projection can still show that the original logical relationship was planned
39456
+ or deprecated. Annotations cannot decorate assignments; use a comment above the
39457
+ assignment when you only need a local authoring hint.
39198
39458
 
39199
39459
  ## Presentation Syntax
39200
39460
 
@@ -39515,11 +39775,13 @@ at context level. Prefer capability language over endpoint trivia.
39515
39775
  Use \`~>\` for meaningful asynchronous context flows:
39516
39776
 
39517
39777
  \`\`\`insight
39518
- links:
39519
- ~> analytics_platform
39520
- technology = Kafka
39521
- via = order.completed
39522
- description = Publishes completed order events
39778
+ external system analytics_platform
39779
+ name = Analytics Platform
39780
+ links:
39781
+ ~> storefront
39782
+ technology = Kafka
39783
+ via = order.completed
39784
+ description = Consumes completed order events from Storefront
39523
39785
  \`\`\`
39524
39786
 
39525
39787
  ## What Not To Put In C1
@@ -39568,6 +39830,22 @@ the selected source file, so a C2 file should usually contain the selected
39568
39830
  \`system <id>\` declaration or an \`extend system <id>\` block with its
39569
39831
  containers/services.
39570
39832
 
39833
+ ## C2 Purity vs Pragmatic Infrastructure
39834
+
39835
+ The clean C2 answer is logical: deployable containers/services and how they
39836
+ collaborate. In that mode, databases, brokers, gateways, vaults, compute, and
39837
+ regions belong to C4/deployment.
39838
+
39839
+ Archinsight does not force that choice. For a quick or single-environment model,
39840
+ it is acceptable to put simple infrastructure-like runtime nodes into C2 when
39841
+ the user wants speed over strict layer separation. Be explicit about the
39842
+ tradeoff: the C2 view becomes mixed, C4 is not really modeled for that system,
39843
+ and many-to-many deployment across different environments will not be available
39844
+ until the model is migrated to clean C4.
39845
+
39846
+ Choose this per system. Do not make the whole repository clean or mixed just
39847
+ because one system needs that style.
39848
+
39571
39849
  ## C2 Workflow
39572
39850
 
39573
39851
  1. Run \`archinsight structure . --format text\` to find the exact system id,
@@ -39691,21 +39969,33 @@ Import the real declaration when it is shared.
39691
39969
 
39692
39970
  ## Async and Eventing Pattern
39693
39971
 
39694
- Use \`~>\` for meaningful asynchronous relationships:
39972
+ Use \`~>\` for meaningful asynchronous dependencies. For pub/sub, declare the
39973
+ wire on the consumer, pointing at the producer/source whose topic contract it
39974
+ depends on:
39695
39975
 
39696
39976
  \`\`\`insight
39697
- service checkout_api
39698
- name = Checkout API
39977
+ external system analytics_platform
39978
+ name = Analytics Platform
39979
+ technology = Kafka consumer
39699
39980
  links:
39700
- ~> analytics_platform
39981
+ ~> checkout_api
39701
39982
  technology = Kafka
39702
39983
  via = checkout.completed
39703
- description = Publishes completed checkout events
39984
+ description = Consumes completed checkout events
39985
+
39986
+ service checkout_api
39987
+ name = Checkout API
39988
+ description = Publishes checkout.completed as an event contract
39704
39989
  \`\`\`
39705
39990
 
39706
- Do not add a broker node just to make an event diagram look familiar. A broker
39707
- is usually deployment/C4 infrastructure unless the project defines it as a
39708
- runtime system or service in the selected view.
39991
+ Do not list consumers under the producer just to answer "who listens to this
39992
+ topic?" That answer belongs in a query over incoming async dependencies.
39993
+
39994
+ Do not add a broker node just to make an event diagram look familiar. In clean
39995
+ C2, a broker is usually deployment/C4 infrastructure unless the project defines
39996
+ it as a runtime system or service in the selected view. In pragmatic mixed C2,
39997
+ adding a broker can be acceptable for a quick view, but it means the diagram is
39998
+ no longer strictly logical C2.
39709
39999
 
39710
40000
  ## C2 Link Details
39711
40001
 
@@ -39726,8 +40016,9 @@ details at C2 only when they clarify the architecture; otherwise use a plain
39726
40016
  ## What Not To Put In C2
39727
40017
 
39728
40018
  - Components, classes, handlers, repositories, or UI widgets.
39729
- - Deployment nodes, pods, regions, network gateways, or secret stores unless the
39730
- project models them as C2 runtime systems.
40019
+ - Deployment nodes, pods, regions, network gateways, or secret stores in clean
40020
+ C2. Include them only when the user intentionally wants pragmatic mixed C2 or
40021
+ the project models them as C2 runtime systems.
39731
40022
  - Database tables and internal schemas.
39732
40023
  - One-off scripts or build-time tools unless they are real runtime units.
39733
40024
  - Duplicate links already represented at a lower C3 level unless the C2 view is
@@ -39736,7 +40027,8 @@ details at C2 only when they clarify the architecture; otherwise use a plain
39736
40027
  ## Common C2 Mistakes
39737
40028
 
39738
40029
  - Adding C2 nodes directly under \`context\` instead of under a \`system\`.
39739
- - Modeling infrastructure that belongs to C4/deployment.
40030
+ - Modeling infrastructure in C2 without deciding that the system is using the
40031
+ pragmatic mixed-C2 style.
39740
40032
  - Mixing C2 container/service links with C3 component links in the same source
39741
40033
  file without a clear view goal.
39742
40034
  - Forgetting \`--source <c2-file.ai>\` when rendering C2.
@@ -39909,10 +40201,6 @@ extend service inventory_api
39909
40201
  links:
39910
40202
  -> inventory_policy
39911
40203
  -> reservation_repository
39912
- ~> inventory_events
39913
- technology = Kafka
39914
- via = inventory.reserved
39915
- description = Publishes successful reservation events
39916
40204
 
39917
40205
  component inventory_policy
39918
40206
  name = Inventory policy
@@ -39924,15 +40212,21 @@ extend service inventory_api
39924
40212
  technology = SQL
39925
40213
  responsibility = Stores reservation state and idempotency keys
39926
40214
 
39927
- component inventory_events
39928
- name = Inventory events
39929
- technology = Kafka producer
39930
- responsibility = Publishes inventory domain events for downstream systems
40215
+ component stock_projection
40216
+ name = Stock projection
40217
+ technology = Kafka consumer
40218
+ responsibility = Maintains a stock read model from reservation events
40219
+ links:
40220
+ ~> reservation_service
40221
+ technology = Kafka
40222
+ via = inventory.reserved
40223
+ description = Consumes successful reservation events
39931
40224
  \`\`\`
39932
40225
 
39933
40226
  Use \`->\` for synchronous calls and \`~>\` for asynchronous flows. Use singular
39934
40227
  \`call\` for the synchronous operation and \`via\` for the asynchronous topic,
39935
- queue, or channel.
40228
+ queue, or channel. For pub/sub, put the async link on the consumer and point it
40229
+ at the producer/source whose event contract it consumes.
39936
40230
 
39937
40231
  ## Imported Boundary Pattern
39938
40232
 
@@ -40011,9 +40305,9 @@ Use async details for events:
40011
40305
 
40012
40306
  \`\`\`insight
40013
40307
  links:
40014
- ~> inventory_events
40308
+ ~> reservation_service
40015
40309
  via = inventory.reserved
40016
- description = Publishes reservation completion
40310
+ description = Consumes reservation completion events
40017
40311
  \`\`\`
40018
40312
 
40019
40313
  Do not add a broker as a component unless the broker is actually part of the
@@ -40056,10 +40350,13 @@ projection rules.
40056
40350
  ## Contents
40057
40351
 
40058
40352
  - What C4 Answers
40353
+ - Before You Use C4
40059
40354
  - Mental Model
40060
40355
  - C4 Workflow
40356
+ - C4 Decision Checklist
40061
40357
  - Environment Inventory
40062
40358
  - Why Infrastructure Is Per Environment
40359
+ - Graph Model vs Diagram Scope
40063
40360
  - Attaching Deployment To C1-C3 Elements
40064
40361
  - usesProfile, environmentsFrom, runsOn, and uses
40065
40362
  - Deployment Archetypes
@@ -40081,6 +40378,31 @@ C4 is not just another decomposition level. C1-C3 mostly describe logical
40081
40378
  architecture. C4 maps logical elements and links onto environment-local
40082
40379
  infrastructure inventory.
40083
40380
 
40381
+ ## Before You Use C4
40382
+
40383
+ C4/deployment is optional. Do not push the user into environments, projection
40384
+ rules, and infrastructure inventory when they only need a quick logical/runtime
40385
+ view.
40386
+
40387
+ If the work has reached infrastructure, runtime placement, regions, compute, or
40388
+ deployment, ask or infer the intended style for the current system:
40389
+
40390
+ - Pragmatic mixed C2: put simple infrastructure-like runtime nodes such as a
40391
+ database, broker, gateway, or vault near the services in C2. This is fast and
40392
+ easier for simple or single-environment systems, but it mixes abstraction
40393
+ levels and does not produce a real C4 model.
40394
+ - Clean C4: keep C2 logical and describe physical realization through
40395
+ \`Environment\` slots, deployment profiles, inventory, \`runsOn\`, \`uses\`,
40396
+ and projection rules. This takes more design work, but supports region/env
40397
+ differences, many-to-many deployment, and organization-specific runtime
40398
+ complexity.
40399
+
40400
+ The choice is per-system. Model a critical system with clean C4 and keep a
40401
+ peripheral system pragmatic in C2 if that matches the user's needs. If a system
40402
+ starts as mixed C2 and later needs multi-env deployment, expect a migration:
40403
+ infrastructure nodes must move into environment inventory and links must gain
40404
+ deployment/projection semantics.
40405
+
40084
40406
  ## Mental Model
40085
40407
 
40086
40408
  There are three layers:
@@ -40148,6 +40470,23 @@ environment prod
40148
40470
  8. Validate with \`archinsight link . --format text\`.
40149
40471
  9. Render with \`archinsight render . -c <context-id> -s <c4-file.ai> -v c4 -f svg -o c4.svg\`.
40150
40472
 
40473
+ ## C4 Decision Checklist
40474
+
40475
+ Use this before adding a \`deployment:\` block:
40476
+
40477
+ - Placement/grouping? Put \`runsOn compute\` on the deployed element.
40478
+ - Stateful or sidecar-like dependency? Put \`uses storage\`, \`uses observability\`,
40479
+ or similar element-level infrastructure on the deployed element.
40480
+ - Traffic path to a target? Put \`uses network\`, \`uses publicGateway\`, or any
40481
+ infrastructure whose projection mentions \`$to\` on the relationship under
40482
+ \`links:\`, not on the container/service.
40483
+ - Pub/sub path? Make the async wire consumer-owned: the consumer declares
40484
+ \`~> producer\` with \`via = <topic>\`, then attach \`uses broker\` to that wire
40485
+ when modeling clean C4 broker infrastructure.
40486
+ - Picture too noisy? Keep the graph model correct and change source scope or
40487
+ write a custom query. Fan-in to a shared node is normal graph reality, not a
40488
+ modeling error by itself.
40489
+
40151
40490
  ## Environment Inventory
40152
40491
 
40153
40492
  Define infrastructure vocabulary in a definition file:
@@ -40220,6 +40559,12 @@ environment prod
40220
40559
  specific \`prod\` environment. Another environment can fill the same slots with
40221
40560
  different concrete infrastructure.
40222
40561
 
40562
+ Object ids are still unique within a context, even when the instances live in
40563
+ different environment slots. When the exact id is not important, use anonymous
40564
+ \`_\` instances inside each environment. When you need stable ids, make them
40565
+ environment-specific, such as \`envoy_prod\` and \`envoy_staging\`, instead of
40566
+ reusing \`envoy_public\` in several environments.
40567
+
40223
40568
  ## Why Infrastructure Is Per Environment
40224
40569
 
40225
40570
  Infrastructure must be per environment because deployment is many-to-many:
@@ -40236,6 +40581,14 @@ If infrastructure were modeled as global nodes, the model could not say:
40236
40581
  "Checkout API runs on EKS in production, Cloud Run in staging, and uses a
40237
40582
  different database in each environment" without duplicating logical services.
40238
40583
 
40584
+ ## Graph Model vs Diagram Scope
40585
+
40586
+ The linked model is a graph; a diagram is only one scoped query over that graph.
40587
+ Fan-in to one broker, gateway, load balancer, or producer is often the correct
40588
+ physical model. If the picture explodes, do not rewrite the model just to make
40589
+ the image tidy. Narrow the selected source file, add a custom \`.aiq\` query,
40590
+ group differently, or aggregate the view.
40591
+
40239
40592
  ## Attaching Deployment To C1-C3 Elements
40240
40593
 
40241
40594
  \`deployment\` is available on systems, containers/services, components, and
@@ -40250,7 +40603,27 @@ Prefer C2 containers/services for most deployment mapping:
40250
40603
  Use C1 deployment only when the whole system is deployed as one unit. Use C3
40251
40604
  deployment when a component is independently deployed or has a distinct physical
40252
40605
  path. Use wire deployment when a specific logical relationship travels through
40253
- infrastructure such as a public gateway, private gateway, broker, or egress path.
40606
+ infrastructure such as a public gateway, network connection, broker, or egress
40607
+ path.
40608
+
40609
+ ## Element-Level vs Wire-Level Infrastructure
40610
+
40611
+ Attach infrastructure to an element when the projection only needs the deployed
40612
+ element itself:
40613
+
40614
+ - \`runsOn compute\`: placement/grouping.
40615
+ - \`uses storage\`: the element depends on stateful infrastructure.
40616
+ - \`uses observability\`: monitoring sidecars or collectors around the element.
40617
+
40618
+ Attach infrastructure to a wire when the projection needs a real target:
40619
+
40620
+ - \`uses publicGateway\`: expands a caller-to-service path through ingress.
40621
+ - \`uses network\`: keeps a direct source-to-target network path on C4.
40622
+ - \`uses broker\`: both producer and consumer physically connect to the broker.
40623
+
40624
+ Rule of thumb: if the infrastructure type's \`project:\` block mentions \`$to\`,
40625
+ use it on a relationship under \`links:\`. Using it on an element is invalid
40626
+ because an element deployment has no separate target endpoint.
40254
40627
 
40255
40628
  ## usesProfile, environmentsFrom, runsOn, and uses
40256
40629
 
@@ -40367,7 +40740,6 @@ deploymentProfile global_service
40367
40740
  global_edge
40368
40741
 
40369
40742
  runsOn compute
40370
- uses publicGateway
40371
40743
 
40372
40744
  deploymentProfile regional_service
40373
40745
  environments:
@@ -40384,6 +40756,11 @@ container web_app
40384
40756
  name = Web app
40385
40757
  deployment:
40386
40758
  usesProfile global_service
40759
+ links:
40760
+ -> checkout_api
40761
+ deployment:
40762
+ environmentsFrom global_service
40763
+ uses publicGateway
40387
40764
 
40388
40765
  service checkout_api
40389
40766
  name = Checkout API
@@ -40392,18 +40769,19 @@ service checkout_api
40392
40769
  uses storage
40393
40770
  \`\`\`
40394
40771
 
40395
- The profile supplies the common environment scope, placement, and standard
40772
+ The profile supplies the common environment scope, placement, and element-level
40396
40773
  infrastructure. Additional local \`uses\` entries extend the profile for that
40397
40774
  specific element. In the example, \`checkout_api\` inherits regional compute and
40398
40775
  observability from \`regional_service\`, then adds its own \`uses storage\`
40399
- because this service owns persistent state.
40776
+ because this service owns persistent state. The \`web_app -> checkout_api\` wire uses
40777
+ \`environmentsFrom global_service\` to reuse the environment list while attaching
40778
+ the path-only \`publicGateway\` projection to the relationship.
40400
40779
 
40401
- Use separate profiles when the default infrastructure differs. For example,
40402
- \`public_regional_service\` can include both \`uses observability\` and
40403
- \`uses publicGateway\`, while \`regional_worker\` may use the same environments,
40404
- compute, and observability but omit public ingress. Put path-only infrastructure
40405
- such as \`network\` on the wire deployment when it represents a specific
40406
- service-to-service path.
40780
+ Use separate profiles when the element-level defaults differ. For example,
40781
+ \`regional_service\` can include \`runsOn compute\` and \`uses observability\`,
40782
+ while \`regional_stateful_service\` can also include \`uses storage\`. Keep
40783
+ path-only infrastructure such as \`publicGateway\`, \`network\`, or \`broker\`
40784
+ on the wire deployment where the source and target are known.
40407
40785
 
40408
40786
  When an element should reuse only the environments from an archetype, use
40409
40787
  \`environmentsFrom <profile>\` instead of \`usesProfile <profile>\` and then add
@@ -40467,6 +40845,10 @@ queries commonly select projected deployment edges; a plain logical wire without
40467
40845
  deployment projection may be correct in C2/C3 but absent from the deployment
40468
40846
  layer.
40469
40847
 
40848
+ If validation reports \`PROJECTION_TARGET_REQUIRED\`, you attached a projection
40849
+ that uses \`$to\` to an element. Move that \`uses ...\` entry to the relevant
40850
+ wire and reuse the element's environment scope with \`environmentsFrom\`.
40851
+
40470
40852
  Projection terms:
40471
40853
 
40472
40854
  - \`$from\` is the logical source of the deployment use.
@@ -40551,7 +40933,6 @@ deploymentProfile public_regional_service
40551
40933
 
40552
40934
  runsOn compute
40553
40935
  uses observability
40554
- uses publicGateway
40555
40936
 
40556
40937
  service checkout_api
40557
40938
  name = Checkout API
@@ -40604,7 +40985,8 @@ logical service projects into both environments without duplicating
40604
40985
  - Logical components invented only to represent physical routing.
40605
40986
  - C3 internals unless they are independently deployed.
40606
40987
  - Cloud resources with no relationship to a deployment question.
40607
- - A broker/gateway/load balancer in C2 just because it appears in deployment.
40988
+ - A broker/gateway/load balancer in C2 just because it appears in deployment,
40989
+ unless the system intentionally uses the pragmatic mixed-C2 style.
40608
40990
 
40609
40991
  ## Common C4 Mistakes
40610
40992
 
@@ -40612,7 +40994,13 @@ logical service projects into both environments without duplicating
40612
40994
  slots for them.
40613
40995
  - Creating \`infrastructureComponent\` nodes at context level when they should
40614
40996
  live in an \`environment\` inventory slot.
40997
+ - Reusing the same concrete infrastructure id in several environments. Use
40998
+ anonymous \`_\` instances or environment-specific ids.
40615
40999
  - Using \`usesProfile\` on a wire when only \`environmentsFrom\` is intended.
41000
+ - Attaching \`uses publicGateway\`, \`uses network\`, or another \`$to\`-based
41001
+ path projection to a container/service. Move it to the specific wire.
41002
+ - Modeling pub/sub as a producer-owned subscriber list. Consumers should declare
41003
+ \`~> producer\` with \`via = <topic>\`; use queries to list consumers.
40616
41004
  - Forgetting \`--source <c4-file.ai>\` when rendering C4.
40617
41005
  - Expecting \`runsOn\` to draw traffic; use \`project:\` rules and \`uses\` for
40618
41006
  traffic/path projections.
@@ -40630,6 +41018,272 @@ Use \`examples/c4-deployment-framework.ai\` and \`examples/c4-deployment.ai\` as
40630
41018
  a compact valid C4 model when syntax is unclear.
40631
41019
  `;
40632
41020
  }
41021
+ function genericScalingReference() {
41022
+ return `# Scaling an Archinsight Repository
41023
+
41024
+ Use this reference when a project grows beyond one or two files and you need to
41025
+ reuse definitions, environments, deployment profiles, or systems without
41026
+ duplicating them.
41027
+
41028
+ ## Repository Shape
41029
+
41030
+ Prefer one shared framework per repository:
41031
+
41032
+ - one definitions/framework area for \`extend type Environment\`, custom
41033
+ infrastructure types, presentation tweaks, projection-capable infrastructure,
41034
+ and reusable deployment profiles;
41035
+ - source files grouped by context directories when the repository is large;
41036
+ - model files that usually focus on one primary owned system being detailed;
41037
+ - one or more inventory files for concrete \`environment <id>\` instances and
41038
+ their env-local infrastructure;
41039
+ - shared external contexts for external actors and systems reused by many
41040
+ systems;
41041
+ - focused deployment-view files that attach deployment profiles and per-view
41042
+ traffic paths.
41043
+
41044
+ Do not copy the same \`extend type Environment\`, infra type definitions, or
41045
+ \`deploymentProfile\` blocks into every system file. Define the vocabulary and
41046
+ reusable archetypes once, import or reference them where needed, and validate the
41047
+ whole project.
41048
+
41049
+ ## Framework Once, Use Everywhere
41050
+
41051
+ A typical deployment framework file contains only shared vocabulary: type
41052
+ definitions, type extensions, projection rules, and presentation overrides. Do
41053
+ not mix \`define type\` / \`extend type\` declarations and \`context\`
41054
+ declarations in the same source file.
41055
+
41056
+ \`\`\`insight
41057
+ define type PublicGateway of InfrastructureComponent
41058
+ constructor publicGateway
41059
+ required InfrastructureComponent cdn
41060
+ required InfrastructureComponent loadBalancer
41061
+
41062
+ project:
41063
+ $from -> cdn
41064
+ cdn -> loadBalancer
41065
+ loadBalancer -> $this
41066
+ $this -> $to
41067
+
41068
+ extend type Environment
41069
+ Compute compute
41070
+ Storage storage
41071
+ Broker broker
41072
+ PublicGateway publicGateway
41073
+ NetworkConnection network
41074
+ \`\`\`
41075
+
41076
+ Concrete inventory/profile files then declare contexts, environments, and
41077
+ profiles:
41078
+
41079
+ \`\`\`insight
41080
+ context infra
41081
+ name = Shared Infrastructure
41082
+
41083
+ environment prod_eu
41084
+ name = Production EU
41085
+ compute:
41086
+ compute ecs
41087
+ name = ECS
41088
+ technology = AWS ECS
41089
+ broker:
41090
+ broker kafka
41091
+ name = Kafka
41092
+ technology = MSK
41093
+ address = kafka.prod.eu.internal
41094
+
41095
+ deploymentProfile regional_service
41096
+ environments:
41097
+ prod_eu
41098
+
41099
+ runsOn compute
41100
+ \`\`\`
41101
+
41102
+ System files should reuse these definitions instead of recreating \`compute\`,
41103
+ \`broker\`, or profile declarations locally.
41104
+
41105
+ ## System Files and External Contexts
41106
+
41107
+ The default model file is centered on one owned system:
41108
+
41109
+ \`\`\`text
41110
+ commerce/
41111
+ checkout.ai
41112
+ catalog.ai
41113
+ fulfillment.ai
41114
+ external/
41115
+ platforms.ai
41116
+ regulators.ai
41117
+ \`\`\`
41118
+
41119
+ \`commerce/checkout.ai\` would declare \`context commerce\`, the
41120
+ \`system checkout\` focal object, and the containers/services/components needed
41121
+ to explain checkout. \`commerce/catalog.ai\` would do the same for catalog.
41122
+
41123
+ Shared external actors and systems should not be copied into every system file.
41124
+ Put them in one external context, or a few semantically grouped external
41125
+ contexts:
41126
+
41127
+ \`\`\`insight
41128
+ context external_platforms
41129
+
41130
+ external system stripe
41131
+ name = Stripe
41132
+
41133
+ external system sendgrid
41134
+ name = SendGrid
41135
+ \`\`\`
41136
+
41137
+ Then import them where needed:
41138
+
41139
+ \`\`\`insight
41140
+ context commerce
41141
+
41142
+ import stripe from context external_platforms
41143
+
41144
+ system checkout
41145
+ links:
41146
+ -> stripe from external_platforms
41147
+ \`\`\`
41148
+
41149
+ Avoid making a separate file for every external actor or vendor unless the
41150
+ external dependency itself has substantial reusable structure. A small number of
41151
+ well-named external contexts gives all repository systems one shared vocabulary
41152
+ for outside dependencies.
41153
+
41154
+ When a system file becomes too large, split details by extending the focal
41155
+ object in utility subdirectories:
41156
+
41157
+ \`\`\`text
41158
+ commerce/
41159
+ checkout.ai
41160
+ checkout-components/
41161
+ pricing.ai
41162
+ payment.ai
41163
+ inventory.ai
41164
+ \`\`\`
41165
+
41166
+ Those files should repeat the same \`context commerce\`, explicitly import the
41167
+ object being extended when it lives in another source file, and use
41168
+ \`extend service checkout_api\`, \`extend container web_app\`, or another object
41169
+ extension to add focused details.
41170
+
41171
+ ## Same-Context Cross-File Imports
41172
+
41173
+ Insight resolves unqualified ids in this order: declarations in the same source
41174
+ file, explicit imports in the same source file, then it reports an error if the
41175
+ same id exists only in another source file of the same context.
41176
+
41177
+ That means splitting one context across files still requires imports:
41178
+
41179
+ \`\`\`insight
41180
+ context services
41181
+
41182
+ deploymentProfile eu_service
41183
+ \`\`\`
41184
+
41185
+ \`\`\`insight
41186
+ context services
41187
+
41188
+ import eu_service from context services
41189
+
41190
+ system checkout
41191
+ name = Checkout
41192
+ deployment:
41193
+ usesProfile eu_service
41194
+ \`\`\`
41195
+
41196
+ This is intentional. If a file is extracted, removed, or not included in the
41197
+ project, the linker should fail with an explicit identifier/import diagnostic
41198
+ instead of silently binding to whatever remains in the context.
41199
+
41200
+ ## Inline from Context
41201
+
41202
+ When a relationship target is declared outside the current source file, prefer
41203
+ an explicit context qualifier on the link target:
41204
+
41205
+ \`\`\`insight
41206
+ context commerce
41207
+
41208
+ import payments from context external_systems
41209
+
41210
+ system checkout
41211
+ name = Checkout
41212
+ links:
41213
+ -> payments from external_systems
41214
+ technology = HTTPS
41215
+ call = POST /payments
41216
+ \`\`\`
41217
+
41218
+ The \`import <id> from context <context-id>\` line documents the dependency and
41219
+ makes the id available for attributes such as profiles and environment slots.
41220
+ The inline \`from <context-id>\` on a link target states which context owns the
41221
+ linked element. Use the same pattern for same-context cross-file links when the
41222
+ source has been split and ambiguity matters:
41223
+
41224
+ \`\`\`insight
41225
+ context services
41226
+
41227
+ import inventory_api from context services
41228
+
41229
+ system checkout_api
41230
+ links:
41231
+ -> inventory_api from services
41232
+ technology = HTTPS
41233
+ call = GET /inventory
41234
+ \`\`\`
41235
+
41236
+ This explicitness is useful during refactors: if the source file holding
41237
+ \`inventory_api\` disappears, validation points at the missing declaration
41238
+ instead of creating a hidden dependency on file layout.
41239
+
41240
+ ## C4 Multi-File Pattern
41241
+
41242
+ For C4, keep these responsibilities separate:
41243
+
41244
+ - framework file: type extensions, infra constructors, presentation/projection
41245
+ definitions;
41246
+ - inventory/profile file: concrete environments and reusable deployment
41247
+ profiles;
41248
+ - deployment-view file: the relationships whose deployment path you want to
41249
+ render for one selected view.
41250
+
41251
+ When rendering C4 with \`-s <source.ai>\`, remember that source/tab scoping is
41252
+ part of the view. Put the view-driving logical relationships in the selected
41253
+ source file, or render from the source file that owns those relationships. Keep
41254
+ imported framework and inventory reusable, but validate the rendered C4 output
41255
+ after moving traffic relationships across files:
41256
+
41257
+ \`\`\`shell
41258
+ archinsight link . --format text
41259
+ archinsight render . -c deployment_shop -s c4-deployment.ai -v c4 -f svg -o deployment-c4.svg
41260
+ \`\`\`
41261
+
41262
+ If projected infrastructure edges disappear after a split, first check whether
41263
+ the selected \`-s\` file still contains the source logical relationship or an
41264
+ intended imported deployment-view relationship. Do not fix that by duplicating
41265
+ infrastructure nodes; fix the source selection or the file boundary.
41266
+
41267
+ ## Practical Workflow
41268
+
41269
+ 1. Run \`archinsight structure . --format text\`.
41270
+ 2. Identify contexts, source files, and declaration ids before editing.
41271
+ 3. Move shared vocabulary into one framework file.
41272
+ 4. Group model files by context directory when the repository is large.
41273
+ 5. Keep each ordinary system file focused on one owned system being detailed.
41274
+ 6. Put external actors/systems in shared external contexts, not one file per
41275
+ external element.
41276
+ 7. Move reusable environments and deployment profiles into inventory/profile
41277
+ files.
41278
+ 8. Add explicit imports for every cross-file dependency, including same-context
41279
+ dependencies.
41280
+ 9. Add inline \`from <context-id>\` on relationship targets that live outside
41281
+ the current source file.
41282
+ 10. Validate with \`archinsight link . --format text\`.
41283
+ 11. Render important C1/C2/C3/C4 views with explicit \`-c\`, \`-s\`, and \`-v\`
41284
+ options.
41285
+ `;
41286
+ }
40633
41287
  function genericProjectStructureReference() {
40634
41288
  return `# Project Structure Workflow
40635
41289
 
@@ -40637,6 +41291,37 @@ Use \`archinsight structure\` before broad edits, imports, or declaration lookup
40637
41291
  Do not start with raw grep when you need to know what the linked project
40638
41292
  contains.
40639
41293
 
41294
+ ## Source File Classes
41295
+
41296
+ Keep source files in one role:
41297
+
41298
+ - definition/framework files: \`define type\`, \`define operator\`,
41299
+ \`define presentation\`, \`extend type\`, \`extend enum of\`, and
41300
+ \`extend presentation\`;
41301
+ - model files: \`context <id>\`, imports, graph object declarations,
41302
+ relationships, environments, and deployment profiles.
41303
+
41304
+ Do not mix definition/framework declarations with \`context <id>\` in one file.
41305
+ When a model needs custom vocabulary, add or edit a framework file first, then
41306
+ use the resulting constructors and attributes from model files.
41307
+
41308
+ ## Directory and File Granularity
41309
+
41310
+ For larger repositories, group model files by context directory. Inside a
41311
+ context directory, default to one primary owned system per ordinary model file:
41312
+ the system that will be detailed by containers, services, components, links, and
41313
+ deployment information.
41314
+
41315
+ External actors and systems are different. Put reusable outside dependencies in
41316
+ one external context or a few semantically grouped external contexts. Do not
41317
+ create a separate file for every external actor or vendor unless that external
41318
+ dependency has real internal structure to model.
41319
+
41320
+ If a system needs further splitting, create a utility subdirectory for focused
41321
+ \`extend <object>\` files, such as per-service component files. Import the
41322
+ extended object explicitly when it is declared in another source file. Keep the
41323
+ main system file as the readable entry point.
41324
+
40640
41325
  ## Commands
40641
41326
 
40642
41327
  Human-readable overview:
@@ -40684,6 +41369,33 @@ links:
40684
41369
  -> payments from external_systems
40685
41370
  \`\`\`
40686
41371
 
41372
+ Imports are also required when a declaration lives in another source file of the
41373
+ same context:
41374
+
41375
+ \`\`\`insight
41376
+ context services
41377
+
41378
+ import eu_service from context services
41379
+
41380
+ system checkout_api
41381
+ deployment:
41382
+ usesProfile eu_service
41383
+ \`\`\`
41384
+
41385
+ The explicit import is intentional. If the source file that declared
41386
+ \`eu_service\` is removed or excluded, validation should fail with a clear
41387
+ missing import/identifier diagnostic instead of depending on hidden file layout.
41388
+
41389
+ For links, \`from <context-id>\` on the target is an inline context qualifier:
41390
+
41391
+ \`\`\`insight
41392
+ links:
41393
+ -> inventory_api from services
41394
+ \`\`\`
41395
+
41396
+ Use it when the relationship target is owned by another context or another
41397
+ source file whose context ownership should remain visible at the call site.
41398
+
40687
41399
  Do not guess context ids from filenames. Filenames, context ids, and element ids
40688
41400
  can differ.
40689
41401
 
@@ -41141,6 +41853,16 @@ diagram needs stable layout.
41141
41853
 
41142
41854
  ## Built-In View Patterns
41143
41855
 
41856
+ Exact built-in query sources are bundled in:
41857
+
41858
+ \`\`\`text
41859
+ examples/builtin-views/no-filter.aiq
41860
+ examples/builtin-views/c1.aiq
41861
+ examples/builtin-views/c2.aiq
41862
+ examples/builtin-views/c3.aiq
41863
+ examples/builtin-views/c4.aiq
41864
+ \`\`\`
41865
+
41144
41866
  C1 usually selects systems in the selected context and rolls lower-level links
41145
41867
  up to system-level relationships.
41146
41868
 
@@ -41153,6 +41875,10 @@ and returns component relationships.
41153
41875
  C4 usually selects deployment and container nodes from \`$tab\`, uses
41154
41876
  \`OPTIONAL MATCH ROLLUP\`, and returns projected relationships.
41155
41877
 
41878
+ When a built-in view is close but hides the wrong thing, read
41879
+ \`references/query-recipes.md\`, copy the nearest built-in \`.aiq\`, and change
41880
+ the filter or grouping deliberately.
41881
+
41156
41882
  ## Authoring Rules
41157
41883
 
41158
41884
  - Start from the view question: context, containers, components, or deployment.
@@ -41163,6 +41889,207 @@ C4 usually selects deployment and container nodes from \`$tab\`, uses
41163
41889
  - Keep custom queries in \`.aiq\` files when they are reused.
41164
41890
  `;
41165
41891
  }
41892
+ function genericQueryRecipesReference() {
41893
+ return `# Query Recipes and Built-In View Customization
41894
+
41895
+ Use this reference when a built-in C1/C2/C3/C4 view is close but not quite right:
41896
+ an expected element is hidden, a relationship is missing, infrastructure is too
41897
+ noisy, or the diagram needs a different scope.
41898
+
41899
+ ## Start From Built-In Queries
41900
+
41901
+ The generated skill includes exact built-in view queries:
41902
+
41903
+ \`\`\`text
41904
+ examples/builtin-views/no-filter.aiq
41905
+ examples/builtin-views/c1.aiq
41906
+ examples/builtin-views/c2.aiq
41907
+ examples/builtin-views/c3.aiq
41908
+ examples/builtin-views/c4.aiq
41909
+ \`\`\`
41910
+
41911
+ Before inventing a query from scratch, open the nearest built-in query, copy it
41912
+ to the project, and make the smallest change.
41913
+
41914
+ \`\`\`shell
41915
+ archinsight query . -c <context-id> -s <source.ai> -q queries/custom.aiq -f text
41916
+ archinsight render . -c <context-id> -s <source.ai> -q queries/custom.aiq -f svg -o custom.svg
41917
+ \`\`\`
41918
+
41919
+ Use \`references/queries.md\` for syntax details. Use this file for common
41920
+ customization patterns.
41921
+
41922
+ ## When To Customize
41923
+
41924
+ Write or adjust a \`.aiq\` query when:
41925
+
41926
+ - the built-in view hides a node or edge that exists in \`archinsight link\`;
41927
+ - the source/tab scope is right but the view intentionally filters out a type;
41928
+ - C4 should include actors, vendors, or a special deployment path;
41929
+ - the diagram should show only one layer, one flow, or one relationship class;
41930
+ - grouping needs to change, such as grouping by parent instead of \`runsOn\`.
41931
+
41932
+ Do not compensate for a view filter by duplicating model elements. First inspect
41933
+ the built-in query and decide whether the model or the query owns the behavior.
41934
+
41935
+ ## Graph Is Not The Picture
41936
+
41937
+ The linked model can have correct fan-in to one broker, gateway, load balancer,
41938
+ producer, or shared runtime node. A crowded diagram means the current view is too
41939
+ broad or not aggregated enough; it does not automatically mean the model is
41940
+ wrong.
41941
+
41942
+ When the graph is right but the picture is noisy:
41943
+
41944
+ - narrow \`-s <source.ai>\` to the file that owns the view;
41945
+ - copy the nearest \`examples/builtin-views/*.aiq\` query;
41946
+ - filter to the layer, flow, or relationship class the user asked for;
41947
+ - change \`GROUP BY\` to cluster by parent, runtime placement, or another useful
41948
+ attribute.
41949
+
41950
+ Do not duplicate infrastructure or invert dependencies only to make one render
41951
+ look cleaner.
41952
+
41953
+ ## Diagnose A Missing Element
41954
+
41955
+ 1. Validate the model:
41956
+
41957
+ \`\`\`shell
41958
+ archinsight link . --format text
41959
+ \`\`\`
41960
+
41961
+ 2. Inspect declarations and source identities:
41962
+
41963
+ \`\`\`shell
41964
+ archinsight structure . --format text
41965
+ \`\`\`
41966
+
41967
+ 3. Run the built-in query text explicitly:
41968
+
41969
+ \`\`\`shell
41970
+ archinsight query . -c <context-id> -s <source.ai> -q examples/builtin-views/c4.aiq -f text
41971
+ \`\`\`
41972
+
41973
+ 4. Check the query filters:
41974
+
41975
+ - \`node.sourceIdentity = $tab\` means the node must be declared in the selected
41976
+ source file.
41977
+ - \`node IS DeploymentElement\` hides actors and ordinary logical elements.
41978
+ - \`{projected}\` means only derived deployment projection edges are selected.
41979
+ - \`{derived}\` means only rolled-up relationships are selected.
41980
+ - \`sourceIdentity: $tab\` on an edge means the relationship/projection must come
41981
+ from the selected source.
41982
+
41983
+ ## Include External Actors In C4
41984
+
41985
+ The built-in C4 query focuses on deployment/container nodes. If a deployment
41986
+ diagram needs the external actor that starts the traffic path, copy
41987
+ \`examples/builtin-views/c4.aiq\` and widen the node and projected target filters:
41988
+
41989
+ \`\`\`cypher
41990
+ MATCH (node:Element)
41991
+ WHERE node.sourceIdentity = $tab
41992
+ AND (node IS DeploymentElement OR node IS ContainerElement OR node IS Actor)
41993
+ OPTIONAL MATCH ROLLUP (node)-[projectedLink {projected, sourceIdentity: $tab}]->(projectedTarget:Element)
41994
+ WHERE projectedTarget IS DeploymentElement
41995
+ OR projectedTarget IS ContainerElement
41996
+ OR projectedTarget IS External
41997
+ OR projectedTarget IS Actor
41998
+ OPTIONAL MATCH (node)-[directDeploymentLink {sourceIdentity: $tab}]->(directDeploymentTarget:Element)
41999
+ WHERE node IS DeploymentElement
42000
+ AND (directDeploymentTarget IS DeploymentElement OR directDeploymentTarget IS External)
42001
+ GROUP BY node.runsOn
42002
+ RETURN node, projectedLink, projectedTarget, directDeploymentLink, directDeploymentTarget
42003
+ \`\`\`
42004
+
42005
+ If the actor is declared in another source file, either render from that source
42006
+ or relax the \`node.sourceIdentity = $tab\` condition intentionally.
42007
+
42008
+ ## Show Only Async Flows
42009
+
42010
+ Use edge attributes when the question is about relationship kind:
42011
+
42012
+ \`\`\`cypher
42013
+ MATCH (source:Element)-[link]->(target:Element)
42014
+ WHERE source.context = $context
42015
+ AND link.model = 'async'
42016
+ GROUP BY source.parent
42017
+ RETURN source, link, target
42018
+ \`\`\`
42019
+
42020
+ This is useful for event-stream, broker, queue, or notification diagrams. Add
42021
+ \`source.sourceIdentity = $tab\` when the query should stay scoped to one file.
42022
+
42023
+ ## Hide Deployment Infrastructure
42024
+
42025
+ When a C4-oriented source file is too noisy and you only need logical containers
42026
+ or services, select logical container elements and direct logical relationships:
42027
+
42028
+ \`\`\`cypher
42029
+ MATCH (node:ContainerElement)
42030
+ WHERE node.sourceIdentity = $tab
42031
+ OPTIONAL MATCH (node)-[link]->(target:ContainerElement)
42032
+ GROUP BY node.parent
42033
+ RETURN node, link, target
42034
+ \`\`\`
42035
+
42036
+ This is intentionally closer to C2 than C4. Use it when deployment annotations
42037
+ exist in the file but the diagram question is still logical.
42038
+
42039
+ ## Show Projected Edges Across Split Files
42040
+
42041
+ The built-in C4 query restricts projected edges to \`sourceIdentity: $tab\`. That
42042
+ is usually correct for a focused deployment-view source file, but it can hide
42043
+ projected edges when traffic relationships were split across files.
42044
+
42045
+ Copy \`examples/builtin-views/c4.aiq\` and relax only the projected edge selector:
42046
+
42047
+ \`\`\`cypher
42048
+ MATCH (node:Element)
42049
+ WHERE node.sourceIdentity = $tab
42050
+ AND (node IS DeploymentElement OR node IS ContainerElement)
42051
+ OPTIONAL MATCH ROLLUP (node)-[projectedLink {projected}]->(projectedTarget:Element)
42052
+ WHERE projectedTarget IS DeploymentElement
42053
+ OR projectedTarget IS ContainerElement
42054
+ OR projectedTarget IS External
42055
+ OPTIONAL MATCH (node)-[directDeploymentLink {sourceIdentity: $tab}]->(directDeploymentTarget:Element)
42056
+ WHERE node IS DeploymentElement
42057
+ AND (directDeploymentTarget IS DeploymentElement OR directDeploymentTarget IS External)
42058
+ GROUP BY node.runsOn
42059
+ RETURN node, projectedLink, projectedTarget, directDeploymentLink, directDeploymentTarget
42060
+ \`\`\`
42061
+
42062
+ Use this deliberately. Removing the source filter can bring in projections from
42063
+ other view files, so validate the result with \`archinsight query\` before
42064
+ rendering.
42065
+
42066
+ ## Change Grouping
42067
+
42068
+ Grouping controls visual clusters. If C4 grouping by \`runsOn\` is not helpful,
42069
+ try grouping by parent:
42070
+
42071
+ \`\`\`cypher
42072
+ MATCH (node:Element)
42073
+ WHERE node.sourceIdentity = $tab
42074
+ AND (node IS DeploymentElement OR node IS ContainerElement)
42075
+ OPTIONAL MATCH ROLLUP (node)-[projectedLink {projected, sourceIdentity: $tab}]->(projectedTarget:Element)
42076
+ WHERE projectedTarget IS DeploymentElement
42077
+ OR projectedTarget IS ContainerElement
42078
+ OR projectedTarget IS External
42079
+ GROUP BY node.parent
42080
+ RETURN node, projectedLink, projectedTarget
42081
+ \`\`\`
42082
+
42083
+ Use \`GROUP BY node.runsOn\` for deployment placement; use \`GROUP BY node.parent\`
42084
+ for logical ownership.
42085
+
42086
+ ## Working Rule
42087
+
42088
+ If a diagram looks wrong but \`archinsight link\` is clean, inspect the selected
42089
+ source, built-in query, and returned aliases before changing the model. Many
42090
+ display issues are query scope issues, not schema or linker bugs.
42091
+ `;
42092
+ }
41166
42093
  function genericLayeredArchitectureExample() {
41167
42094
  return `context shop
41168
42095
  name = Shop Platform
@@ -41346,6 +42273,11 @@ external system payment_provider
41346
42273
  external system analytics_platform
41347
42274
  name = Analytics Platform
41348
42275
  technology = Kafka consumer
42276
+ links:
42277
+ ~> checkout_api
42278
+ technology = Kafka
42279
+ via = checkout.completed
42280
+ description = Consumes completed checkout events
41349
42281
 
41350
42282
  system storefront
41351
42283
  name = Storefront
@@ -41376,12 +42308,6 @@ system storefront
41376
42308
  name = Checkout API
41377
42309
  technology = Kotlin, PostgreSQL
41378
42310
  description = Prices carts, creates orders, and coordinates payment
41379
- links:
41380
- ~> analytics_platform
41381
- technology = Kafka
41382
- via = checkout.completed
41383
- description = Publishes completed checkout events
41384
-
41385
42311
  component checkout_controller
41386
42312
  name = Checkout controller
41387
42313
  technology = REST controller
@@ -41398,10 +42324,6 @@ system storefront
41398
42324
  call = authorize(paymentCommand)
41399
42325
  description = Requests payment authorization
41400
42326
  -> order_repository
41401
- ~> checkout_events
41402
- technology = Kafka
41403
- via = checkout.completed
41404
- description = Publishes completed checkout events
41405
42327
 
41406
42328
  component payment_gateway
41407
42329
  name = Payment gateway
@@ -41418,10 +42340,15 @@ system storefront
41418
42340
  technology = SQL
41419
42341
  responsibility = Stores order state and checkout audit records
41420
42342
 
41421
- component checkout_events
41422
- name = Checkout events
41423
- technology = Kafka producer
41424
- responsibility = Publishes checkout lifecycle events for downstream consumers
42343
+ component checkout_projection
42344
+ name = Checkout projection
42345
+ technology = Kafka consumer
42346
+ responsibility = Maintains an internal checkout read model from events
42347
+ links:
42348
+ ~> checkout_service
42349
+ technology = Kafka
42350
+ via = checkout.completed
42351
+ description = Consumes checkout completion events
41425
42352
  `;
41426
42353
  }
41427
42354
  function genericC4DeploymentFrameworkExample() {
@@ -41490,7 +42417,6 @@ deploymentProfile public_regional_service
41490
42417
 
41491
42418
  runsOn compute
41492
42419
  uses observability
41493
- uses publicGateway
41494
42420
 
41495
42421
  environment prod
41496
42422
  name = Production
@@ -41619,11 +42545,25 @@ system storefront
41619
42545
  deployment:
41620
42546
  usesProfile regional_service
41621
42547
  uses storage
41622
- uses broker
41623
42548
  links:
41624
42549
  -> payment_provider
41625
42550
  technology = HTTPS
41626
42551
  call = POST /payments/authorizations
42552
+
42553
+ service order_worker
42554
+ name = Order Worker
42555
+ technology = Kotlin
42556
+ description = Processes order events asynchronously
42557
+ deployment:
42558
+ usesProfile regional_service
42559
+ links:
42560
+ ~> checkout_api
42561
+ technology = Kafka
42562
+ via = orders.events
42563
+ description = Consumes order events emitted by Checkout API
42564
+ deployment:
42565
+ environmentsFrom regional_service
42566
+ uses broker
41627
42567
  `;
41628
42568
  }
41629
42569
  function genericC2QueryExample() {