Fix review findings: importer DoS, sync data loss, views/profile rendering, docs
Source importers: lstat before open so FIFOs no longer hang the directory walk; replace the quadratic Rust macro regex with a linear scan. Three-way sync: report page add/add and delete-vs-modify as conflicts instead of silently overwriting or resurrecting; canonical comparison so key order is not a change; the sync action withholds output and fails on conflicts unless --force. Story publishing escapes <, >, & and U+2028/9 inside the embedded JSON. Views: drop parentId of unselected containers, re-layout instead of manual geometry, validate before serialising; flatten() merges identical nodes repeated across pages so C4 output works with every analysis action. Dark theme edge labels get a background; tube-map corridors sit above the stations; C4 containers keep the swimlane style and orphan relationships land on the matching page; router keeps container header bands as obstacles; sequence self-messages loop on one side. Docs: SKILL.md lists all 23 CLI actions and how each capability family is invoked, task wrappers for query/test/what-if/doctor, capability tables and --page scope corrected, maintenance snippet uses the real synchronous action signature, duplicated rule bullets moved to the rule references, coverage matrix wording made verifiable. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Agents365 capability coverage
|
||||
|
||||
> Evidence basis: clean-room behavioral comparison of 42 peer tools. Peer source and bundled assets were not copied because the inspected mirror had no complete license file.
|
||||
> Evidence basis: internal comparison against a 42-entry peer-tool feature list (tool names as listed in the matrix; no version or commit was recorded, so the comparison is **not independently verifiable**). Peer source and bundled assets were not copied. The "Native evidence" column points to files in this repository and is verifiable; the "Remaining gap" column reflects the internal feature list only.
|
||||
|
||||
## Reading the classifications
|
||||
|
||||
@@ -32,16 +32,16 @@ These are strict peer-parity labels. A `partial` row can still contain substanti
|
||||
| `ciimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | The service imports a bounded generic jobs/needs object, but lacks CLI registration, repository workflow discovery, triggers, runners, matrices, reusable workflows, GitLab stages, and inferred stage dependencies. |
|
||||
| `composeimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | Services, depends_on, and simple named volumes are covered through a service API; links, volumes_from, long-form mounts, network grouping, conventional-file discovery, and CLI exposure remain absent. |
|
||||
| `compress.py` | **partial** | `scripts/src/services/profiles/compression.ts`<br>`scripts/src/services/profiles/compression.test.ts` | A deterministic BFS clustering service emits summary and full IR pages, but there is no Draw.io-facing action, exact loss-aware detail-file workflow, label-propagation parity, or member-cell drill-down target contract. |
|
||||
| `dbxicons.py` | **optional-deferred** | `scripts/src/services/shape-catalog/shape-catalog.ts`<br>clean-room 42-tool mapping audit | No licensed Databricks manifest, aliases, variants, pinned-ref embedding, refresh operation, host allowlist, or CLI action was delivered. |
|
||||
| `dbxicons.py` | **optional-deferred** | `scripts/src/services/shape-catalog/shape-catalog.ts`<br>internal peer feature-list comparison (not independently verifiable) | No licensed Databricks manifest, aliases, variants, pinned-ref embedding, refresh operation, host allowlist, or CLI action was delivered. |
|
||||
| `diagram_ir.py` | **partial** | `scripts/src/model/diagram-ir.ts`<br>`scripts/src/services/semantic-lifecycle/import-drawio.ts`<br>`scripts/src/services/semantic-lifecycle/analysis.ts`<br>`scripts/src/services/semantic-lifecycle/sync.ts`<br>`scripts/src/services/semantic-lifecycle/publishing.ts` | Versioned IR, loss-aware import, views, query, policies, failure impact, sync, and story publishing exist, but articulation analysis, a unified architecture-review contract, contrast analysis, multilingual labeling, and explicit peer-IR-v1 compatibility are incomplete. |
|
||||
| `diagramctl.py` | **partial** | `scripts/src/cli/commands.ts`<br>`scripts/src/cli/semantic-lifecycle.test.ts`<br>`scripts/src/actions/doctor/action.ts`<br>`scripts/src/actions/sync/action.ts` | Lifecycle actions are registered in the existing --action CLI, but integrated importer, profile, transform, and reverse-export services are not registered. There is no uniform peer-equivalent result envelope. |
|
||||
| `diagramctl_mcp.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>clean-room 42-tool mapping audit | No optional MCP package, JSON-RPC initialization, tools/list, tools/call bridge, closed schemas, timeout handling, or MCP entrypoint exists. |
|
||||
| `diagramctl_mcp.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>internal peer feature-list comparison (not independently verifiable) | No optional MCP package, JSON-RPC initialization, tools/list, tools/call bridge, closed schemas, timeout handling, or MCP entrypoint exists. |
|
||||
| `dockerimports.py` | **optional-deferred** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | The importer registry has Docker Compose but no Docker inspect snapshot kind, container/network/volume instance normalization, redaction contract, stdin parity, or action. |
|
||||
| `drawio2mermaid.py` | **partial** | `scripts/src/services/transforms/reverse.ts`<br>`scripts/src/services/transforms/reverse.test.ts`<br>`scripts/src/services/semantic-lifecycle/import-drawio.ts` | A deterministic IR-to-Mermaid service exists, but there is no Draw.io-to-Mermaid CLI/action, shape-form mapping, direction/fence controls, or lossy-conversion report. |
|
||||
| `drawio2pptx.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>clean-room 42-tool mapping audit | No optional Draw.io renderer adapter, per-page raster loop, PPTX writer, slide sizing, scale option, or structured unavailable result exists. |
|
||||
| `drawio2pptx.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>internal peer feature-list comparison (not independently verifiable) | No optional Draw.io renderer adapter, per-page raster loop, PPTX writer, slide sizing, scale option, or structured unavailable result exists. |
|
||||
| `drawiodiff.py` | **partial** | `scripts/src/services/transforms/semantic-diff.ts`<br>`scripts/src/services/transforms/semantic-diff.test.ts`<br>`scripts/src/services/semantic-lifecycle/import-drawio.ts` | The IR service classifies added, removed, changed, moved, and rerouted entities, but no CLI/action composes Draw.io import with diffing, no by-label ambiguity mode exists, and no color-coded graph output or summary diagram is emitted. |
|
||||
| `drawiohtml.py` | **optional-deferred** | `scripts/src/services/semantic-lifecycle/publishing.ts`<br>`scripts/src/actions/story/action.ts` | Story HTML is a different semantic publisher; there is no page-to-SVG export adapter, SVG sanitizer, tabbed viewer, pan/zoom/search UI, drill-down link rewrite, or publish-viewer action. |
|
||||
| `edgeports.py` | **rejected** | `scripts/src/services/authoring-router/orthogonal-router.ts`<br>`scripts/src/services/authoring-router/orthogonal-router.test.ts`<br>clean-room 42-tool mapping audit | Only routing during authoring exists. The post-import boundary-port editor, pinned-port preservation, dry-run, idempotence, and transactional Draw.io write path were not selected for this post-phase implementation. |
|
||||
| `edgeports.py` | **rejected** | `scripts/src/services/authoring-router/orthogonal-router.ts`<br>`scripts/src/services/authoring-router/orthogonal-router.test.ts`<br>internal peer feature-list comparison (not independently verifiable) | Only routing during authoring exists. The post-import boundary-port editor, pinned-port preservation, dry-run, idempotence, and transactional Draw.io write path were not selected for this post-phase implementation. |
|
||||
| `encode_drawio_url.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>`scripts/package.json` | Compression primitives are available transitively, but there is no byte-compatible URL encoder, viewer/edit modes, size policy, privacy warning, or CLI action. |
|
||||
| `explain.py` | **partial** | `scripts/src/services/transforms/reverse.ts`<br>`scripts/src/services/transforms/reverse.test.ts` | Structured Markdown for IR pages, nodes, and flows exists as a service, but no Draw.io-facing explain action, tier/type inference, C4 context, unknown-section reporting, or output-file contract is exposed. |
|
||||
| `goimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | Bounded Go import extraction exists, but it emits imported paths as library nodes rather than resolving only intra-module packages; module discovery, grouping, transitive reduction, and CLI exposure are absent. |
|
||||
@@ -54,14 +54,14 @@ These are strict peer-parity labels. A `partial` row can still contain substanti
|
||||
| `pyimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | Bounded import/from extraction and dynamic-import diagnostics exist, but relative and absolute intra-project resolution, stdlib/third-party exclusion, package grouping, transitive reduction, syntax-error diagnostics, and CLI exposure are absent. |
|
||||
| `raster2drawio.py` | **partial** | `scripts/src/actions/build/action.ts`<br>`scripts/src/authoring/ir-to-drawio.ts`<br>`scripts/src/services/layout/layout-engine.ts`<br>`scripts/src/model/diagram-ir.ts` | Generic IR build supports explicit geometry, styles, edges, and automatic layout, but there is no raster-extracted graph compatibility schema/action, x/y/w/h shorthand conversion, partial-coordinate policy, confidence/provenance convention, or extraction-warning envelope. |
|
||||
| `relabel.py` | **partial** | `scripts/src/services/transforms/relabel.ts`<br>`scripts/src/services/transforms/relabel.test.ts` | A strict complete-map IR relabel service preserves non-label structure, but there is no extraction mode, page-name handling, UserObject traversal contract, partial-map/unmatched reporting, Draw.io transactional write, or CLI action. |
|
||||
| `repair_png.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>clean-room 42-tool mapping audit | No PNG chunk validator, signature-specific repair, atomic in-place replacement, idempotence gate, version gate, or optional action exists. |
|
||||
| `repair_png.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>internal peer feature-list comparison (not independently verifiable) | No PNG chunk validator, signature-specific repair, atomic in-place replacement, idempotence gate, version gate, or optional action exists. |
|
||||
| `restyle.py` | **partial** | `scripts/src/services/themes/theme-service.ts`<br>`scripts/src/services/themes/theme-service.test.ts` | Five validated built-in themes and immutable IR application exist, but the peer-style palette-slot schema, user preset loader, hue/neutral color remapping, global extras, versioned JSON schema, Draw.io transactional action, and CLI exposure are incomplete. |
|
||||
| `runbook.py` | **partial** | `scripts/src/services/profiles/runbook.ts`<br>`scripts/src/services/profiles/runbook.test.ts` | The service emits escaped self-contained interactive HTML from an explicit RunbookGraph, but it does not parse Draw.io, infer node types/start nodes/choices, report fallback selection, or expose a publish-runbook action. |
|
||||
| `rustimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | A bounded subset recognizes mod and simple use roots and diagnoses macros, but crate/self/super resolution, module-file discovery, complete brace expansion, external-crate exclusion, grouping, reduction, and CLI exposure are absent. |
|
||||
| `seqlayout.py` | **partial** | `scripts/src/services/profiles/sequence.ts`<br>`scripts/src/services/profiles/sequence.test.ts` | Participants, ordered messages, lifelines, activations, return validation, and editable geometry are implemented as a service, but notes are unsupported and no sequence schema file, input action, direction/options contract, or CLI registration exists. |
|
||||
| `shapesearch.py` | **partial** | `scripts/src/services/shape-catalog/shape-catalog.ts`<br>`scripts/src/services/shape-catalog/shape-catalog.test.ts` | Deterministic exact/alias/fuzzy search exists for eight hand-curated generic shapes, not the licensed 10k+ palette index; compound/tag/Soundex ranking, dimensions, gzip integrity controls, expected ecosystem queries, and CLI output are missing. |
|
||||
| `sqlerd.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | A narrow line-oriented subset finds simple tables and REFERENCES edges, but columns/types, PK/FK markers, quoted/schema identifiers, composite keys, schema grouping, crow's-foot styles, unsupported-syntax diagnostics, and CLI exposure are missing. |
|
||||
| `svgflow.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>clean-room 42-tool mapping audit | No optional Draw.io SVG export adapter, SVG parser/sanitizer, connector detection, animation injection, reduced-motion handling, or export-flow-svg action exists. |
|
||||
| `svgflow.py` | **optional-deferred** | `scripts/src/cli/commands.ts`<br>internal peer feature-list comparison (not independently verifiable) | No optional Draw.io SVG export adapter, SVG parser/sanitizer, connector detection, animation injection, reduced-motion handling, or export-flow-svg action exists. |
|
||||
| `tfimports.py` | **partial** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | A bounded line-oriented resource/reference subset exists, but modules, multiline/nested HCL handling, comments/string false-positive guarantees, diagnostics for dynamic expressions, cloud styles, grouping, transitive reduction, no-icons mode, and CLI exposure are incomplete. |
|
||||
| `tfstate.py` | **optional-deferred** | `scripts/src/services/source-importers/index.ts`<br>`scripts/src/services/source-importers/index.test.ts` | No Terraform show-JSON snapshot source kind, nested module traversal, count/for_each instance expansion, sensitive-value redaction, state relationship extraction, stdin parity, or optional action exists. |
|
||||
| `timelapse.py` | **partial** | `scripts/src/services/profiles/timelapse.ts`<br>`scripts/src/services/profiles/timelapse.test.ts` | The service classifies changes across caller-supplied IR snapshots, but it has no scoped git history/archive adapter, deterministic commit sampling, importer allowlist, Draw.io frame rendering, HTML player, resource limits, or CLI action. |
|
||||
@@ -71,7 +71,3 @@ These are strict peer-parity labels. A `partial` row can still contain substanti
|
||||
## Architectural boundary
|
||||
|
||||
The retained implementation stays in the existing TypeScript/Node.js stack with pnpm, Taskfile, `@maxgraph/core`, and the established action-based CLI. Python, Graphviz, Eclipse Layout Kernel (ELK), Model Context Protocol (MCP), browser services, network icon retrieval, and Draw.io Desktop are not mandatory dependencies. Optional adapters must report availability honestly.
|
||||
|
||||
## Delivery note
|
||||
|
||||
This matrix describes the combined integrated candidate and deliberate scope decisions. Gitea publication and Hermes runtime installation are separate gates and must not be inferred from this document.
|
||||
+81
-50
@@ -1,12 +1,12 @@
|
||||
# diagrams-drawio — Capabilities
|
||||
|
||||
This file lists all capabilities an agent can use from this skill.
|
||||
This file lists all capabilities an agent can use from this skill. The seven capability families below use the same headings and order as the list at the top of [SKILL.md](../SKILL.md).
|
||||
|
||||
---
|
||||
|
||||
## Capability 1 — Deterministic YAML generation
|
||||
|
||||
Build native `.drawio` XML from a validated semantic Diagram IR:
|
||||
Build native `.drawio` XML from a validated semantic Diagram IR (CLI action `build`, `task generate`):
|
||||
|
||||
```bash
|
||||
node dist/cli/commands.js --action build --file architecture.yaml --output architecture.drawio
|
||||
@@ -18,22 +18,14 @@ IR v1 remains compatible. IR v2 adds multiple pages, containers and semantic kin
|
||||
|
||||
## Capability 2 — Direct XML generation
|
||||
|
||||
Create `.drawio` files (and optionally export to PNG/SVG/PDF) from a description or requirements.
|
||||
Create `.drawio` files (and optionally export to PNG/SVG/PDF) from a description or requirements. The agent authors the mxGraphModel XML directly and then runs the mandatory `validate` action (`task validate`).
|
||||
|
||||
See [SKILL.md](../SKILL.md) for the generation workflow, XML format, page sizes, element shapes, and well-formedness rules.
|
||||
See [rules-layout.md](./rules-layout.md) for mandatory connector and layout rules.
|
||||
See [rules-layout.md](./rules-layout.md) and [rules-style.md](./rules-style.md) for mandatory connector, layout, and style rules.
|
||||
|
||||
---
|
||||
|
||||
## Capability 3 — Semantic lifecycle
|
||||
|
||||
The native TypeScript core supports loss-aware Draw.io import and deterministic round trips; transactional stable-ID edit batches; linked audience views; semantic query, architecture policy, and failure what-if analysis; three-way synchronization; accessible self-contained story HTML; and a non-launching doctor report.
|
||||
|
||||
See [semantic-lifecycle.md](./semantic-lifecycle.md) for command contracts, safety behavior, built-in policy identifiers, and examples.
|
||||
|
||||
---
|
||||
|
||||
## Capability 4 — Diagram analysis (drawio-tools CLI)
|
||||
## Capability 3 — Diagram analysis (drawio-tools CLI)
|
||||
|
||||
A **TypeScript / Node.js** CLI tool for programmatic analysis of `.drawio` files.
|
||||
Entry point: `node dist/cli/commands.js` (run from the skill's `scripts/` directory), or `task run -- --file=… --action=…`.
|
||||
@@ -46,7 +38,7 @@ node dist/cli/commands.js --file <path> --action <action> [--page <index>] [--ou
|
||||
# short flags: -f, -a, -p, -o, -h
|
||||
```
|
||||
|
||||
`--page` selects the diagram tab (0-based, default 0). Ignored by `summary` (processes all pages).
|
||||
`--page` selects the diagram tab (0-based, default 0). Only the actions marked `--page` below honour it; actions marked "page 0 only" always analyse the first page, and all-page actions ignore it.
|
||||
Always prints YAML to stdout. Exit code `0` on success, `1` on error.
|
||||
|
||||
### Actions
|
||||
@@ -57,7 +49,41 @@ Always prints YAML to stdout. Exit code `0` on success, `1` on error.
|
||||
|---|---|---|
|
||||
| `build` | YAML Diagram IR | Validate and convert a YAML specification to native `.drawio`; requires `--output` |
|
||||
|
||||
#### Semantic lifecycle
|
||||
#### Inventory
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `summary` | All pages | Full inventory of shapes + edges for every page/tab |
|
||||
| `page-summary` | `--page` | Full inventory of shapes + edges for one page |
|
||||
| `page-hierarchy` | `--page` | Recursive containment tree with totalLevels (nesting depth count) |
|
||||
| `page-hierarchy-full` | `--page` | Same as page-hierarchy + full geometry (x, y, width, height) per shape at each nesting level |
|
||||
| `page-connectors-summary` | page 0 only | Per-connector details: type, label, waypoints, source/target names |
|
||||
|
||||
#### Validation
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `validate` | All pages | **Mandatory final gate** — XML well-formedness + maxGraph compile + sanity check (vertices/edges > 0). Run before finishing any diagram work |
|
||||
| `quality` | All pages | Objective clipping, overflow, placeholder, external-asset, palette, page-density, and edge-density checks with explicit severity |
|
||||
| `page-connectors-validation` | page 0 only | Connector-shape overlaps + connector crossings + corner-port, header-edge, and single-port violations |
|
||||
| `page-labels-validation` | page 0 only | Empty labels, duplicate labels, labels > 80 chars |
|
||||
| `page-shape-bbox-validation` | page 0 only | Non-containment bounding box overlaps between shapes |
|
||||
| `page-orphans` | page 0 only | Isolated shapes (no edges) + dangling connectors (missing endpoints) |
|
||||
|
||||
#### Layout
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `page-recommendations` | page 0 only | Smallest standard page size (A4→A3→A2→A1→custom) that fits content with 80 px margin |
|
||||
| `page-negative-space-summary` | `--page` | Free horizontal corridors (negative space) per nesting level, bbox-based and text-aware; input for connector routing and [negative-space-diagram.md](./negative-space-diagram.md) |
|
||||
|
||||
> For install/build instructions, source structure, and how to add new actions, see [maintenance.md](./maintenance.md).
|
||||
|
||||
---
|
||||
|
||||
## Capability 4 — Semantic lifecycle
|
||||
|
||||
The native TypeScript core supports loss-aware Draw.io import and deterministic round trips; transactional stable-ID edit batches; linked audience views; semantic query, architecture policy, and failure what-if analysis; three-way synchronization; accessible self-contained story HTML; and a non-launching doctor report. Every action below also has a same-named `task` wrapper (`task import`, `task edit`, …).
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
@@ -71,44 +97,49 @@ Always prints YAML to stdout. Exit code `0` on success, `1` on error.
|
||||
| `story` | Diagram IR v2 | Write self-contained accessible offline HTML; optional `--fail` overlay |
|
||||
| `doctor` | Local environment | Report optional backend availability without launching processes or requiring a model file |
|
||||
|
||||
#### Inventory
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `summary` | All pages | Full inventory of shapes + edges for every page/tab |
|
||||
| `page-summary` | Single page (`--page`) | Full inventory of shapes + edges for one page |
|
||||
| `page-hierarchy` | Page 0 | Recursive containment tree with totalLevels (nesting depth count) |
|
||||
| `page-hierarchy-full` | Page 0 | Same as page-hierarchy + full geometry (x, y, width, height) per shape at each nesting level |
|
||||
| `page-connectors-summary` | Page 0 | Per-connector details: type, label, waypoints, source/target names |
|
||||
|
||||
#### Validation
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `validate` | All pages | **Mandatory final gate** — XML well-formedness + maxGraph compile + sanity check (vertices/edges > 0). Run before finishing any diagram work |
|
||||
| `quality` | All pages | Objective clipping, overflow, placeholder, external-asset, palette, page-density, and edge-density checks with explicit severity |
|
||||
| `page-connectors-validation` | Page 0 | Connector-shape overlaps + connector crossings |
|
||||
| `page-labels-validation` | Page 0 | Empty labels, duplicate labels, labels > 80 chars |
|
||||
| `page-shape-bbox-validation` | Page 0 | Non-containment bounding box overlaps between shapes |
|
||||
| `page-orphans` | Page 0 | Isolated shapes (no edges) + dangling connectors (missing endpoints) |
|
||||
|
||||
#### Layout
|
||||
|
||||
| Action | Scope | Description |
|
||||
|---|---|---|
|
||||
| `page-recommendations` | Page 0 | Smallest standard page size (A4→A3→A2→A1→custom) that fits content with 80 px margin |
|
||||
|
||||
> For install/build instructions, source structure, and how to add new actions, see [maintenance.md](./maintenance.md).
|
||||
See [semantic-lifecycle.md](./semantic-lifecycle.md) for command contracts, safety behavior, built-in policy identifiers, and examples.
|
||||
|
||||
---
|
||||
|
||||
## Capability 5 — Native service libraries
|
||||
## Capability 5 — Safe source importers
|
||||
|
||||
The package includes additional strict TypeScript APIs under `scripts/src/services/`:
|
||||
**Library only** — not reachable as a CLI action. Import from `dist/services/source-importers/index.js` (source `scripts/src/services/source-importers/index.ts`):
|
||||
|
||||
- `source-importers/` — conservative, bounded source/configuration topology extraction with diagnostics and no code execution;
|
||||
- `themes/` and `shape-catalog/` — five validated themes and an offline generic shape catalog;
|
||||
- `transforms/` — reverse Mermaid/Markdown, semantic diff, complete-map relabeling, and accessible bounded heatmaps;
|
||||
- `profiles/` — C4, sequence, tube map, compression, runbook, timelapse, and build-up profiles.
|
||||
```ts
|
||||
import { importSource } from "<skill>/scripts/dist/services/source-importers/index.js";
|
||||
```
|
||||
|
||||
These services are covered by the native test suite but are not registered CLI actions. Their exact peer-relative coverage and deliberate omissions are listed in [agents365-capability-coverage.md](./agents365-capability-coverage.md).
|
||||
`importSource({ sourceKind, path, input })` performs conservative, bounded topology extraction with diagnostics and no code execution for `python`, `javascript`, `typescript`, `go`, `rust`, `terraform`, `kubernetes`, `docker-compose`, `sql`, `openapi`, and `ci` inputs, returning a Diagram IR v2 plus diagnostics and provenance.
|
||||
|
||||
---
|
||||
|
||||
## Capability 6 — Toolbox transforms
|
||||
|
||||
**Library only** — not reachable as a CLI action. Modules under `dist/services/` (source `scripts/src/services/`):
|
||||
|
||||
| Module | Exports | Purpose |
|
||||
|---|---|---|
|
||||
| `themes/theme-service.js` | `applyTheme`, `validateTheme`, `contrastRatio` | Five validated built-in themes, immutable IR application |
|
||||
| `shape-catalog/shape-catalog.js` | `searchShapes` | Offline generic shape search (exact/alias/fuzzy) |
|
||||
| `transforms/reverse.js` | `diagramIRToMermaid`, `diagramIRToStructuredMarkdown` | Reverse Mermaid / Markdown from IR |
|
||||
| `transforms/semantic-diff.js` | `semanticDiff` | Added/removed/changed/moved/rerouted classification between two IR models |
|
||||
| `transforms/relabel.js` | `relabelDiagram` | Strict complete-map relabeling preserving structure |
|
||||
| `transforms/heatmap.js` | `applyMetricsHeatmap` | Accessible bounded metric heatmaps with legend metadata |
|
||||
|
||||
---
|
||||
|
||||
## Capability 7 — Specialized profiles
|
||||
|
||||
**Library only** — not reachable as a CLI action. Import from `dist/services/profiles/index.js` (source `scripts/src/services/profiles/index.ts`):
|
||||
|
||||
```ts
|
||||
import { projectC4, createSequenceDiagram, createTubeMap, compressExecutiveView,
|
||||
createRunbookHtml, createArchitectureTimelapse, createBuildup }
|
||||
from "<skill>/scripts/dist/services/profiles/index.js";
|
||||
```
|
||||
|
||||
C4 projection, sequence diagram layout, tube map routing, executive-view compression, runbook HTML, architecture timelapse, and dependency-ordered build-up frames.
|
||||
|
||||
---
|
||||
|
||||
Capabilities 5–7 are covered by the native test suite but are not registered CLI actions. Their exact peer-relative coverage and deliberate omissions are listed in [agents365-capability-coverage.md](./agents365-capability-coverage.md).
|
||||
|
||||
@@ -36,7 +36,7 @@ The git repository is the source of truth. Install dependencies and build inside
|
||||
|
||||
```bash
|
||||
cd <skill>/scripts
|
||||
pnpm install
|
||||
pnpm install --frozen-lockfile
|
||||
task build # or: pnpm run build
|
||||
```
|
||||
|
||||
@@ -99,7 +99,11 @@ src/
|
||||
│ │ └── page-summary.ts # buildPageSummary() — shared per-page serialisation helper
|
||||
│ ├── hierarchy-builder/
|
||||
│ │ └── hierarchy-builder.ts # buildHierarchy() — shared BFS depth map + containment tree
|
||||
│ └── semantic-lifecycle/ # import, edit, views/query/policy/what-if, sync, story, atomic I/O
|
||||
│ ├── semantic-lifecycle/ # import, edit, views/query/policy/what-if, sync, story, atomic I/O
|
||||
│ ├── layout/, authoring-router/ # deterministic layout + obstacle-aware routing used by build (ir-to-drawio)
|
||||
│ ├── connector-router/ # edge path reconstruction used by page-connectors-summary/-validation
|
||||
│ ├── maxgraph-loader/ # jsdom polyfill + maxGraph state loader (used by validate and negative-space)
|
||||
│ └── source-importers/, transforms/, themes/, shape-catalog/, profiles/ # library-only services (no CLI action)
|
||||
└── actions/
|
||||
├── build|import|edit|views|query|test|what-if|sync|story|doctor/
|
||||
│ # authoring and semantic lifecycle actions
|
||||
@@ -113,6 +117,8 @@ src/
|
||||
├── page-orphans/ # isolated shapes + dangling connectors
|
||||
├── page-recommendations/ # page size recommendation
|
||||
├── page-hierarchy-full/ # nesting levels with full shape geometry (x, y, width, height)
|
||||
├── page-negative-space-summary/ # free horizontal corridors per nesting level (bbox + text-aware)
|
||||
├── quality/ # all-pages clipping/overflow/placeholder/palette/density checks with severity
|
||||
└── validate/ # MANDATORY final gate — XML well-formedness + maxGraph compile + sanity check
|
||||
```
|
||||
|
||||
@@ -145,25 +151,34 @@ Each action exports `run(filePath, pageIndex?, outputPath?, options?): Record<st
|
||||
|
||||
## Adding a new action
|
||||
|
||||
1. Create `src/actions/<name>/action.ts` exporting:
|
||||
1. Create `src/actions/<name>/action.ts` exporting a **synchronous** `run` (the dispatcher in `commands.ts` reads `result.summary` / `result.failed` without `await`, so an `async` function or a returned `Promise` would break exit-code handling). Copy the signature from an existing action, e.g. `src/actions/page-hierarchy/action.ts`:
|
||||
```ts
|
||||
export async function run(filePath: string, pageIndex?: number): Promise<Record<string, unknown>>
|
||||
export function run(filePath: string, pageIndex: number = 0): Record<string, unknown> {
|
||||
const pages = parseAllPages(filePath);
|
||||
const page = pages[pageIndex];
|
||||
if (!page) {
|
||||
return { error: true, message: `Page index ${pageIndex} not found` };
|
||||
}
|
||||
// ...
|
||||
return { action: "<name>", /* ... */ };
|
||||
}
|
||||
```
|
||||
The full `ActionModule` contract is `run(filePath: string, pageIndex?: number, outputPath?: string, options?: LifecycleActionOptions): Record<string, unknown>`; declare only the parameters you use. Set `failed: true` in the result to make the CLI exit with code `1`.
|
||||
2. Register it in `src/cli/commands.ts` under `ACTIONS`:
|
||||
```ts
|
||||
"my-action": () => import("../actions/my-action/action.js"),
|
||||
```
|
||||
3. Use `parseDiagram(filePath)` (first page) or `parseAllPages(filePath)` (all pages) from the parser
|
||||
3. Use `parseAllPages(filePath)[pageIndex]` to honour `--page`, or `parseDiagram(filePath)` when the action is deliberately page-0-only; `parseAllPages` for all-page actions. Document the choice in the Scope column of `capabilities.md`
|
||||
4. Optionally import `buildPageSummary(page)` from `page-summary.ts` for standard shape/edge serialisation
|
||||
5. Return a plain object — the CLI serialises it to YAML automatically
|
||||
6. Run `pnpm run build` to compile and verify no TypeScript errors
|
||||
6. Run `task build` (or `pnpm run build`) to compile and verify no TypeScript errors, then add the action to `capabilities.md`, the `Actions:` list in `commands.ts --help`, and the Taskfile descriptions
|
||||
|
||||
### Naming convention
|
||||
|
||||
Actions follow `{object}-{action}` naming:
|
||||
|
||||
- `page-*` — operates on a single diagram page (uses `--page`, default 0)
|
||||
- `summary` — operates on all pages
|
||||
- `page-*` — operates on a single diagram page (`page-summary`, `page-hierarchy`, `page-hierarchy-full`, `page-negative-space-summary` honour `--page`; the remaining `page-*` actions currently analyse page 0 only)
|
||||
- `summary`, `validate`, `quality` — operate on all pages
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,7 +27,49 @@ These rules are **MANDATORY** — apply them when generating any diagram.
|
||||
- `startSize=40`, 1 row h=80: total = 40+40+80+40 = 200 (children at y=80)
|
||||
- `startSize=40`, 2 rows h=40 each: total = 40+40+40+40+40+40 = 240 (row1 at y=80, row2 at y=160)
|
||||
|
||||
After generating or editing a diagram, run `page-spacing-audit` and `page-swimlane-audit` to verify.
|
||||
After generating or editing a diagram, run `page-shape-bbox-validation`, `page-connectors-validation`, and `page-hierarchy-full` (geometry per nesting level) to verify.
|
||||
|
||||
### Page size
|
||||
|
||||
- Use page dimensions that fully fit the diagram, **including margins, legends, and connector routing corridors** — never let content clip the page edge
|
||||
- `page-recommendations` reports the smallest standard page size that fits the content with an 80 px margin
|
||||
|
||||
### Parent (container) sizing — MANDATORY
|
||||
|
||||
**A parent shape must always be large enough to fully enclose all its children, including inner padding.** When children grow (added, resized, or repositioned), expand the parent using:
|
||||
|
||||
```
|
||||
parent.width = max_child_right + right_padding (right_padding ≥ 40, divisible by 40)
|
||||
parent.height = max_child_bottom + bottom_padding (bottom_padding ≥ 40, divisible by 40)
|
||||
```
|
||||
|
||||
Where `max_child_right = max(child.x + child.width)` and `max_child_bottom = max(child.y + child.height)` over all children (relative to the parent). Left/top inner padding must also be ≥ 40 pt and divisible by 40 pt.
|
||||
|
||||
- **Cascade rule:** parent expansion may force *its* parent to expand. Walk up the containment tree and resize each ancestor until the outermost container fits all descendants
|
||||
- **Re-check after expansion:** when a parent grows, re-verify sibling spacing at every affected level — all gaps must remain divisible by 40 pt
|
||||
|
||||
### Grouping and complexity
|
||||
|
||||
- Keep diagram complexity medium: group services into logical zones/layers (swimlanes or containers per major domain) instead of scattering many unrelated services
|
||||
- Never route dense connector bundles directly through container titles/headers (see label-crossing prohibition below)
|
||||
|
||||
### Connector labels and legends
|
||||
|
||||
- In dense diagrams keep connector labels **off the connector path**; if labels are needed, place them in a clearly empty corridor, a side note, or a dedicated legend
|
||||
- Prefer a separate legend for flow explanations whenever connector labels would clutter the diagram
|
||||
- Keep legends **outside the main routing area** so no connector crosses legend text
|
||||
- Connector labels must never overlap shapes, cards, icons, or other text
|
||||
|
||||
### Final visual inspection
|
||||
|
||||
Before completion, re-open or visually inspect the diagram and check specifically for:
|
||||
- shape overlap (including external actors, cards, icons, notes, legends, containers)
|
||||
- connector overlap with cards/icons
|
||||
- connector label overlap
|
||||
- text overflowing card boundaries
|
||||
- page clipping
|
||||
- inconsistent spacing between lanes/columns and between rows
|
||||
- missing canonical vendor shapes
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -15,9 +15,17 @@ These rules are **MANDATORY** — apply them when generating any diagram.
|
||||
- **Swimlane body height (total − startSize) must be divisible by 40** — so total height = 40 + N×40 = a multiple of 40
|
||||
- Example: `startSize=40`, body=80 → total=120 ✓; body=160 → total=200 ✓
|
||||
- Use ≤ 3 primary color families; create hierarchy with shades
|
||||
- Use dashed connectors only for semantically distinct flows (async, backup, admin)
|
||||
- Keep connector colors simple and consistent; use dashed connectors only for semantically distinct flows (async, backup, admin, private)
|
||||
- Avoid borders on shapes unless needed for visual separation or canonical styling
|
||||
- Shape size is driven by **content**, not routing — typically 80–160px tall per label line
|
||||
|
||||
### Text fit and cards
|
||||
|
||||
- Avoid long text inside narrow shapes; use wider cards or wrap the label in a dedicated text area inside the card
|
||||
- Service names must fit within the visual card width and never extend beyond card boundaries
|
||||
- For service-card diagrams use one consistent card pattern: icon on the left, service label on the right, enough padding around both
|
||||
- When using canonical vendor icons, **preserve the original icon styling**; adjust the surrounding card/container layout instead of modifying the icon style
|
||||
|
||||
---
|
||||
|
||||
## Connector routing rules — MANDATORY
|
||||
@@ -27,6 +35,7 @@ These rules are **MANDATORY** — apply them when generating any diagram.
|
||||
- **Connectors must never attach at a shape corner** — the exit/entry point must lie on the middle of a side: top-center, bottom-center, left-center, or right-center. A point that is simultaneously on both an X-edge (left or right) AND a Y-edge (top or bottom) of the shape bounding box is a corner and is forbidden. Use the midpoint of the chosen side: `x_mid = (x1+x2)/2` for top/bottom sides, `y_mid = (y1+y2)/2` for left/right sides.
|
||||
- These rules ensure a clean "bus-bar" fan-out/fan-in pattern and prevent connectors from diverging at their source or converging at their target at different positions, which creates visual clutter and increases crossing risk.
|
||||
- Exception: shapes with only a single outgoing or single incoming connector — the single-port rule trivially holds. The corner rule still applies.
|
||||
- **Arrowheads stay outside shape interiors** — connectors touch the shape/card edge and never pass through the body.
|
||||
- When computing waypoints: use `page-negative-space-summary` to find free X corridors per row, then pick an exit/entry coordinate that lies within a free corridor at the next traversed level. This minimises connector-shape overlaps and connector crossings.
|
||||
- **Waypoints must never be closer than 20px to any shape** — the first waypoint after a shape exit must be at least 20px away from the shape's edge in the direction of travel (e.g., if exiting bottom at y=520, first waypoint y ≥ 540; if exiting right at x=1040, first waypoint x ≥ 1060). The last waypoint before a shape entry must likewise be at least 20px away from the shape's edge. This 20px clearance also applies to any waypoint relative to same-level sibling shapes the connector passes by — the waypoint must not come within 20px of any sibling shape's bounding box side it is adjacent to.
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ node dist/cli/commands.js --action edit \
|
||||
--output edited.drawio
|
||||
```
|
||||
|
||||
A batch targets one page and supports typed `add`, `update`, `move`, `delete`, and `connect` operations. Supported preconditions are `exists`, `not-exists`, and `property-equals`, each expressed with a `type` and `id`. Unknown precondition or operation types, update payloads that attempt to change `id`, duplicate identifiers, invalid parents/endpoints, and non-cascading deletion of referenced elements fail closed and abort the entire batch. Dry runs return a preview and write nothing.
|
||||
A batch targets one page and supports typed `add`, `update`, `move`, `delete`, and `connect` operations. Supported preconditions are `exists`, `not-exists`, and `property-equals`, each expressed with a `type` and `id`; `property-equals` additionally requires `property` (the property name) and `value` (the exact expected value). The shipped `examples/edit-batch.yaml` is tied to `examples/platform-v2.yaml` (page `system`, node `api`) — build or import that model first, or adapt the IDs before applying the batch to another model. Unknown precondition or operation types, update payloads that attempt to change `id`, duplicate identifiers, invalid parents/endpoints, and non-cascading deletion of referenced elements fail closed and abort the entire batch. Dry runs return a preview and write nothing.
|
||||
|
||||
## Linked audience views
|
||||
|
||||
|
||||
Reference in New Issue
Block a user