katalyst-forge 4.2.0__tar.gz → 5.1.0__tar.gz
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.
- katalyst_forge-5.1.0/.gitignore +23 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/CHANGELOG.md +39 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/PKG-INFO +1 -1
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/pyproject.toml +1 -1
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/__init__.py +1 -1
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/bundle.py +11 -7
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/relationships.py +67 -3
- katalyst_forge-5.1.0/src/katalyst_forge/wings/_practice_refs.py +58 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/design.py +5 -115
- katalyst_forge-5.1.0/src/katalyst_forge/wings/metrics.py +197 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/org.py +11 -5
- katalyst_forge-5.1.0/src/katalyst_forge/wings/practices.py +565 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/system.py +13 -2
- katalyst_forge-5.1.0/templates/CHANGELOG.md +524 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_entry_point_discovery.py +2 -2
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_forge.py +7 -7
- katalyst_forge-5.1.0/tests/test_practice_assignment.py +107 -0
- katalyst_forge-5.1.0/tests/test_storage_contract.py +66 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_wings.py +22 -2
- katalyst_forge-4.2.0/.gitignore +0 -8
- katalyst_forge-4.2.0/src/katalyst_forge/wings/practices.py +0 -216
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/LICENSE +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/CHANGELOG.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/README.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/agents/agent.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/agents/config.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/agents/manifest.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/agents/skill.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/environment.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/hooks/hook-config.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/katalyst-lock.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/nodes/common.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/nodes/design.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/nodes/organizational.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/nodes/portfolio.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/nodes/technical.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/schemas/taxonomy-node.schema.json +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/py.typed +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/_base.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/layer.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/project.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/stack.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/system.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/team.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/creation/team_member.yaml.j2 +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/.dockerignore +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/.env.example +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/README.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/base/Dockerfile +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/docker-compose.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/env-template/Dockerfile +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/env-template/docker-compose.override.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/env-template/environment.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/app-docker/layer.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/README.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/composite/terraform/main.tf +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/composite/terraform/outputs.tf +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/composite/terraform/variables.tf +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/env-template/environment.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/env-template/terragrunt.hcl +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/global/iac/context.hcl +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/global/iac/dev.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/global/iac/prod.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/global/iac/staging.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/layer.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/iac-terragrunt/version.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/README.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/base/app/argocd-application.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/base/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/base/namespace.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/environment-template/argocd-application.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/environment-template/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/environment-template/patch-argocd-application.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-argocd/layer.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/README.md +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/base/deployment.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/base/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/base/namespace.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/base/service.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/environment-template/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/environment-template/patch-deployment.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/global/k8s/base/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/global/k8s/base/namespace.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/global/k8s/kustomization.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/templates/scaffolds/k8s-kustomize/layer.yaml +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/__init__.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/agentic.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/delivery.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/src/katalyst_forge/wings/pipeline.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/conftest.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_agent_run.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_delivery_doc_consistency.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_delivery_traceability.py +0 -0
- {katalyst_forge-4.2.0 → katalyst_forge-5.1.0}/tests/test_wing_schemas.py +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.pyc
|
|
3
|
+
.venv/
|
|
4
|
+
dist/
|
|
5
|
+
site/
|
|
6
|
+
node_modules/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
|
|
10
|
+
# RIC-733 consistency eval run exhaust (transient, not the checked-in baseline)
|
|
11
|
+
docs/consistency-results.json
|
|
12
|
+
.prompt-cache/
|
|
13
|
+
|
|
14
|
+
# Deterministic tooling-gate run artifacts (kata-gate.sh runtime output).
|
|
15
|
+
# Real telemetry per run; regenerated on every gate invocation, not committed.
|
|
16
|
+
.global/taxonomy/delivery/agent_runs/tooling/
|
|
17
|
+
|
|
18
|
+
# Generated orientation packet (RIC-731): produced at install time, not source
|
|
19
|
+
orientation/packet.json
|
|
20
|
+
|
|
21
|
+
# Machine-local orientation fallback config (RIC-731): holds an absolute packetPath,
|
|
22
|
+
# written beside the installed contract; never source, never commit.
|
|
23
|
+
orientation-config.json
|
|
@@ -16,6 +16,45 @@ PyPI package version. A breaking node-type/model change bumps `schema_version`.
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
+
## [5.1.0] -- 2026-07-28
|
|
20
|
+
|
|
21
|
+
- **Canonical ADR/NFR storage** (RIC-1358) — ADR and NFR definitions now declare flat identity-derived storage under `.global/taxonomy/design/adrs/` and `.global/taxonomy/design/nfrs/`. Forge agents, skills, templates, fixtures, and documentation use the plural directories; legacy multi-document examples are labeled explicitly.
|
|
22
|
+
- Migrated the nine Forge-owned NFR artifacts from `design/nfr/` to `design/nfrs/` and added `NFR-010` to require executable storage consumers to resolve registry metadata instead of hard-coding artifact kinds or paths.
|
|
23
|
+
|
|
24
|
+
## [5.0.0] -- 2026-07-22
|
|
25
|
+
|
|
26
|
+
Bundle `schema_version` bumped to **5** and manifest version to **5.0** to reflect breaking relationship renames and parent-rule changes below.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`practice` node kind** in the Practices wing (RIC-1273). A bundle node that sits between `practice_area` and standards/methods/competencies/tools, enabling strict nesting: `practice_area` → `practice` → `{standard, method, competency, tool}`. Practices are assignable units that reference (do not own) standards and methods.
|
|
31
|
+
- **`INCLUDES_PRACTICE` relationship** (`practice_area` → `practice`): grouping edge for the new strict nesting hierarchy.
|
|
32
|
+
- **`PRESCRIBES_STANDARD` / `PRESCRIBES_METHOD` relationships** (`practice` → `standard` / `method`): practice prescribes which standards and methods it bundles.
|
|
33
|
+
- **`ADHERES_TO_PRACTICE` / `ADHERES_TO_STANDARD` / `ADHERES_TO_METHOD` relationships**: assignment edges allowing consumer nodes (system, stack, layer, library, tool, organization, project, team) to declare which practices, standards, and methods they follow.
|
|
34
|
+
- **Practice assignment fields** (`practices`, `standards`, `methods`) spliced into 8 consumer ("follower") node kinds via shared `_practice_refs.py` helper.
|
|
35
|
+
- **`metric_definition`, `signal_source`, `threshold_profile` node kinds** in the new Metrics wing (RIC-1272). Brings the bundle to **36 node types across 8 wings**.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **BREAKING: `competency` re-parented from `practice_area` to `practice`** (RIC-1273). The `ParentRule.allowed_parent_kinds` changed from `{"practice_area"}` to `{"practice"}`. Any existing `competency` instances parented under a `practice_area` must be re-parented under a `practice` node. No known consuming taxonomies have competency instances.
|
|
40
|
+
- **BREAKING: Relationship renames** (RIC-1273). The following relationship types were renamed for naming consistency (all edge families now use verb-first, actor-centric naming):
|
|
41
|
+
- `INCLUDES_METHOD` / `INCLUDES_STANDARD` → removed (replaced by `PRESCRIBES_STANDARD` / `PRESCRIBES_METHOD` on the new `practice` node)
|
|
42
|
+
- Assignment family unified: `FOLLOWS_PRACTICE` → `ADHERES_TO_PRACTICE`, `APPLIES_METHOD` → `ADHERES_TO_METHOD` (`ADHERES_TO_STANDARD` unchanged)
|
|
43
|
+
- **`standard` and `method` relocated from Design wing to Practices wing** (RIC-1273). `nfr` is now a child of `standard`; `adr` is now a child of `method`. Design wing shrinks from 8 → 6 kinds; Practices wing grows from 4 → 9 kinds.
|
|
44
|
+
|
|
45
|
+
### Migration
|
|
46
|
+
|
|
47
|
+
Consuming taxonomies that reference the removed/renamed relationship types in cross-references or queries must update:
|
|
48
|
+
|
|
49
|
+
| Old | New |
|
|
50
|
+
|-----|-----|
|
|
51
|
+
| `INCLUDES_METHOD` | `PRESCRIBES_METHOD` (on `practice`, not `practice_area`) |
|
|
52
|
+
| `INCLUDES_STANDARD` | `PRESCRIBES_STANDARD` (on `practice`, not `practice_area`) |
|
|
53
|
+
| `FOLLOWS_PRACTICE` | `ADHERES_TO_PRACTICE` |
|
|
54
|
+
| `APPLIES_METHOD` | `ADHERES_TO_METHOD` |
|
|
55
|
+
| `competency` parented under `practice_area` | Re-parent under `practice` |
|
|
56
|
+
| `nfr` / `adr` in design wing | Now in practices wing (no YAML change needed; wing is metadata) |
|
|
57
|
+
|
|
19
58
|
## [4.2.0] -- 2026-07-06
|
|
20
59
|
|
|
21
60
|
Repo split (RIC-1070). First release from the standalone
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""katalyst-forge — The Forge bundle for katalyst-engine.
|
|
2
2
|
|
|
3
|
-
Provides
|
|
3
|
+
Provides 36 node-type definitions across 8 wings for software delivery taxonomy.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Forge bundle — the pre-installed taxonomy for software delivery.
|
|
2
2
|
|
|
3
|
-
Assembles
|
|
3
|
+
Assembles 36 node types across 8 wings from the wing modules into
|
|
4
4
|
a single ``ForgeBundle`` that implements the engine's ``Bundle``
|
|
5
5
|
protocol. Discovered via the ``katalyst_engine.bundles`` entry point.
|
|
6
6
|
|
|
@@ -9,12 +9,13 @@ protocol. Discovered via the ``katalyst_engine.bundles`` entry point.
|
|
|
9
9
|
Wing modules:
|
|
10
10
|
- ``wings/system.py`` — system, environment, stack, layer, library, capability
|
|
11
11
|
- ``wings/org.py`` — organization, program, project, team, team_member, role
|
|
12
|
-
- ``wings/practices.py``
|
|
13
|
-
- ``wings/design.py`` — business_domain_model, user_type, user_need, design_spec,
|
|
12
|
+
- ``wings/practices.py`` — practice_area, practice, competency, skill, standard, nfr, method, adr, tool
|
|
13
|
+
- ``wings/design.py`` — business_domain_model, user_type, user_need, design_spec, specification, assertion
|
|
14
14
|
- ``wings/delivery.py`` — work_item, change_entry, agent_run
|
|
15
15
|
- ``wings/pipeline.py`` — cicd_stage
|
|
16
16
|
- ``wings/pipeline.py`` — cicd_stage, cicd_job_template, cicd_workflow_template
|
|
17
17
|
- ``wings/agentic.py`` — agent, agent_skill
|
|
18
|
+
- ``wings/metrics.py`` — metric_definition, signal_source, threshold_profile
|
|
18
19
|
"""
|
|
19
20
|
|
|
20
21
|
from __future__ import annotations
|
|
@@ -36,6 +37,7 @@ from katalyst_forge.relationships import ALL_RELATIONSHIP_DEFINITIONS
|
|
|
36
37
|
from katalyst_forge.wings.agentic import AGENTIC_WING, AGENTIC_WING_NODES
|
|
37
38
|
from katalyst_forge.wings.delivery import DELIVERY_WING, DELIVERY_WING_NODES
|
|
38
39
|
from katalyst_forge.wings.design import DESIGN_WING, DESIGN_WING_NODES
|
|
40
|
+
from katalyst_forge.wings.metrics import METRICS_WING, METRICS_WING_NODES
|
|
39
41
|
from katalyst_forge.wings.org import ORG_WING, ORG_WING_NODES
|
|
40
42
|
from katalyst_forge.wings.pipeline import PIPELINE_WING, PIPELINE_WING_NODES
|
|
41
43
|
from katalyst_forge.wings.practices import PRACTICES_WING, PRACTICES_WING_NODES
|
|
@@ -53,6 +55,7 @@ ALL_NODE_DEFINITIONS: list[NodeDefinition] = [
|
|
|
53
55
|
*DELIVERY_WING_NODES,
|
|
54
56
|
*PIPELINE_WING_NODES,
|
|
55
57
|
*AGENTIC_WING_NODES,
|
|
58
|
+
*METRICS_WING_NODES,
|
|
56
59
|
]
|
|
57
60
|
|
|
58
61
|
ALL_KINDS: frozenset[str] = frozenset(nd.describes_kind for nd in ALL_NODE_DEFINITIONS)
|
|
@@ -65,6 +68,7 @@ ALL_WING_DEFINITIONS: list[WingDefinition] = [
|
|
|
65
68
|
PRACTICES_WING,
|
|
66
69
|
PIPELINE_WING,
|
|
67
70
|
AGENTIC_WING,
|
|
71
|
+
METRICS_WING,
|
|
68
72
|
]
|
|
69
73
|
|
|
70
74
|
ALL_WING_NAMES: frozenset[str] = frozenset(wd.identity.name for wd in ALL_WING_DEFINITIONS)
|
|
@@ -76,7 +80,7 @@ ALL_WING_NAMES: frozenset[str] = frozenset(wd.identity.name for wd in ALL_WING_D
|
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
class ForgeBundle:
|
|
79
|
-
"""The Forge bundle —
|
|
83
|
+
"""The Forge bundle — 36 node types across 8 wings.
|
|
80
84
|
|
|
81
85
|
This is the pre-installed taxonomy bundle that ships with
|
|
82
86
|
Katalyst Taxonomy. It models software delivery organizations
|
|
@@ -89,10 +93,10 @@ class ForgeBundle:
|
|
|
89
93
|
def manifest(self) -> BundleManifest:
|
|
90
94
|
return BundleManifest(
|
|
91
95
|
identity=Identity(kind="bundle", name="forge"),
|
|
92
|
-
version=Version(major=
|
|
96
|
+
version=Version(major=5, minor=1),
|
|
93
97
|
provided_kinds=ALL_KINDS,
|
|
94
98
|
wing_names=ALL_WING_NAMES,
|
|
95
|
-
description="Forge taxonomy —
|
|
99
|
+
description="Forge taxonomy — 36 node types for modeling software delivery organizations",
|
|
96
100
|
)
|
|
97
101
|
|
|
98
102
|
def node_definitions(self) -> list[NodeDefinition]:
|
|
@@ -109,7 +113,7 @@ class ForgeBundle:
|
|
|
109
113
|
identity=Identity(kind="schema", name="forge"),
|
|
110
114
|
describes_kind="taxonomy",
|
|
111
115
|
api_version="v2alpha",
|
|
112
|
-
schema_version=Version(major=
|
|
116
|
+
schema_version=Version(major=5),
|
|
113
117
|
node_definitions=tuple(nd.identity for nd in ALL_NODE_DEFINITIONS),
|
|
114
118
|
wing_definitions=tuple(wd.identity for wd in ALL_WING_DEFINITIONS),
|
|
115
119
|
)
|
|
@@ -127,16 +127,25 @@ FILLED_BY_REL = RelationshipDefinition(
|
|
|
127
127
|
DEVELOPS_COMPETENCY_REL = RelationshipDefinition(
|
|
128
128
|
identity=_rel_id("develops_competency"),
|
|
129
129
|
describes_kind="develops_competency",
|
|
130
|
-
description="Practice
|
|
130
|
+
description="Practice develops a competency",
|
|
131
131
|
wing="organizational",
|
|
132
132
|
display_order=210,
|
|
133
133
|
cardinality=Cardinality.MANY_TO_MANY,
|
|
134
134
|
)
|
|
135
135
|
|
|
136
|
+
INCLUDES_PRACTICE_REL = RelationshipDefinition(
|
|
137
|
+
identity=_rel_id("includes_practice"),
|
|
138
|
+
describes_kind="includes_practice",
|
|
139
|
+
description="Practice area includes a practice",
|
|
140
|
+
wing="organizational",
|
|
141
|
+
display_order=214,
|
|
142
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
143
|
+
)
|
|
144
|
+
|
|
136
145
|
USES_TOOL_REL = RelationshipDefinition(
|
|
137
146
|
identity=_rel_id("uses_tool"),
|
|
138
147
|
describes_kind="uses_tool",
|
|
139
|
-
description="Practice
|
|
148
|
+
description="Practice uses a tool",
|
|
140
149
|
wing="organizational",
|
|
141
150
|
display_order=220,
|
|
142
151
|
cardinality=Cardinality.MANY_TO_MANY,
|
|
@@ -151,6 +160,55 @@ REQUIRES_SKILL_REL = RelationshipDefinition(
|
|
|
151
160
|
cardinality=Cardinality.MANY_TO_MANY,
|
|
152
161
|
)
|
|
153
162
|
|
|
163
|
+
# ── Practice prescribing (practice → standard/method, referenced not owned) ──
|
|
164
|
+
|
|
165
|
+
PRESCRIBES_STANDARD_REL = RelationshipDefinition(
|
|
166
|
+
identity=_rel_id("prescribes_standard"),
|
|
167
|
+
describes_kind="prescribes_standard",
|
|
168
|
+
description="Practice prescribes a standard",
|
|
169
|
+
wing="organizational",
|
|
170
|
+
display_order=231,
|
|
171
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
PRESCRIBES_METHOD_REL = RelationshipDefinition(
|
|
175
|
+
identity=_rel_id("prescribes_method"),
|
|
176
|
+
describes_kind="prescribes_method",
|
|
177
|
+
description="Practice prescribes a method",
|
|
178
|
+
wing="organizational",
|
|
179
|
+
display_order=232,
|
|
180
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# ── Practice assignment (consumer node → practice/standard/method) ────────
|
|
184
|
+
|
|
185
|
+
ADHERES_TO_PRACTICE_REL = RelationshipDefinition(
|
|
186
|
+
identity=_rel_id("adheres_to_practice"),
|
|
187
|
+
describes_kind="adheres_to_practice",
|
|
188
|
+
description="A node adheres to a practice",
|
|
189
|
+
wing="organizational",
|
|
190
|
+
display_order=233,
|
|
191
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
ADHERES_TO_STANDARD_REL = RelationshipDefinition(
|
|
195
|
+
identity=_rel_id("adheres_to_standard"),
|
|
196
|
+
describes_kind="adheres_to_standard",
|
|
197
|
+
description="A node adheres to a standard",
|
|
198
|
+
wing="organizational",
|
|
199
|
+
display_order=234,
|
|
200
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
ADHERES_TO_METHOD_REL = RelationshipDefinition(
|
|
204
|
+
identity=_rel_id("adheres_to_method"),
|
|
205
|
+
describes_kind="adheres_to_method",
|
|
206
|
+
description="A node adheres to a method",
|
|
207
|
+
wing="organizational",
|
|
208
|
+
display_order=235,
|
|
209
|
+
cardinality=Cardinality.MANY_TO_MANY,
|
|
210
|
+
)
|
|
211
|
+
|
|
154
212
|
# ── Verification wing ────────────────────────────────────────────────
|
|
155
213
|
|
|
156
214
|
VERIFIED_BY_REL = RelationshipDefinition(
|
|
@@ -249,7 +307,7 @@ TRACES_TO_REL = RelationshipDefinition(
|
|
|
249
307
|
identity=_rel_id("traces_to"),
|
|
250
308
|
describes_kind="traces_to",
|
|
251
309
|
description=(
|
|
252
|
-
"Work item traces to a design-wing artifact it implements, addresses, or "
|
|
310
|
+
"Work item traces to a design- or practices-wing artifact it implements, addresses, or "
|
|
253
311
|
"satisfies (capability, user_need, nfr, adr, design_spec, specification). "
|
|
254
312
|
"The target kind is carried by the source field reference, so adding a new "
|
|
255
313
|
"traceable target kind is a one-line field addition, not a new edge type."
|
|
@@ -297,8 +355,14 @@ ALL_RELATIONSHIP_DEFINITIONS: list[RelationshipDefinition] = [
|
|
|
297
355
|
# organizational
|
|
298
356
|
FILLED_BY_REL,
|
|
299
357
|
DEVELOPS_COMPETENCY_REL,
|
|
358
|
+
INCLUDES_PRACTICE_REL,
|
|
300
359
|
USES_TOOL_REL,
|
|
301
360
|
REQUIRES_SKILL_REL,
|
|
361
|
+
PRESCRIBES_STANDARD_REL,
|
|
362
|
+
PRESCRIBES_METHOD_REL,
|
|
363
|
+
ADHERES_TO_PRACTICE_REL,
|
|
364
|
+
ADHERES_TO_STANDARD_REL,
|
|
365
|
+
ADHERES_TO_METHOD_REL,
|
|
302
366
|
# verification
|
|
303
367
|
VERIFIED_BY_REL,
|
|
304
368
|
TESTS_SPECIFICATION_REL,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Shared practice-reference fields for consumer ("follower") node kinds.
|
|
2
|
+
|
|
3
|
+
Any node that can *follow* a practice, *adhere to* a standard, or *apply* a
|
|
4
|
+
method carries the same three cross-reference fields. Rather than duplicate the
|
|
5
|
+
identical ``FieldSpec``/``FieldRef`` blocks across every follower kind in the
|
|
6
|
+
``system``, ``org``, and ``practices`` wings, they are defined once here and
|
|
7
|
+
spliced into each follower's ``fields`` / ``cross_references`` tuples.
|
|
8
|
+
|
|
9
|
+
These edges are the *assignment* side of practices — semantically distinct from
|
|
10
|
+
the *grouping* edges (``INCLUDES_PRACTICE`` on ``practice_area``;
|
|
11
|
+
``PRESCRIBES_STANDARD`` / ``PRESCRIBES_METHOD`` on ``practice``). A follower "adheres
|
|
12
|
+
to" a standard; a practice "prescribes" one; a practice_area "includes" a practice.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from katalyst_engine.schema.definition import FieldRef, FieldSpec
|
|
18
|
+
|
|
19
|
+
#: Fields spliced into every follower kind's ``fields`` tuple.
|
|
20
|
+
PRACTICE_REFERENCE_FIELDS: tuple[FieldSpec, ...] = (
|
|
21
|
+
FieldSpec(
|
|
22
|
+
name="practices",
|
|
23
|
+
field_type="list",
|
|
24
|
+
required=False,
|
|
25
|
+
description="Practices this node follows",
|
|
26
|
+
),
|
|
27
|
+
FieldSpec(
|
|
28
|
+
name="standards",
|
|
29
|
+
field_type="list",
|
|
30
|
+
required=False,
|
|
31
|
+
description="Standards this node adheres to",
|
|
32
|
+
),
|
|
33
|
+
FieldSpec(
|
|
34
|
+
name="methods",
|
|
35
|
+
field_type="list",
|
|
36
|
+
required=False,
|
|
37
|
+
description="Methods this node applies",
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
#: Cross-references spliced into every follower kind's ``cross_references``.
|
|
42
|
+
PRACTICE_REFERENCE_CROSS_REFS: tuple[FieldRef, ...] = (
|
|
43
|
+
FieldRef(
|
|
44
|
+
field_name="practices",
|
|
45
|
+
target_kind="practice",
|
|
46
|
+
rel_type="ADHERES_TO_PRACTICE",
|
|
47
|
+
),
|
|
48
|
+
FieldRef(
|
|
49
|
+
field_name="standards",
|
|
50
|
+
target_kind="standard",
|
|
51
|
+
rel_type="ADHERES_TO_STANDARD",
|
|
52
|
+
),
|
|
53
|
+
FieldRef(
|
|
54
|
+
field_name="methods",
|
|
55
|
+
target_kind="method",
|
|
56
|
+
rel_type="ADHERES_TO_METHOD",
|
|
57
|
+
),
|
|
58
|
+
)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
"""Design wing — business_domain_model, user_type, user_need, design_spec,
|
|
1
|
+
"""Design wing — business_domain_model, user_type, user_need, design_spec, specification, assertion.
|
|
2
|
+
|
|
3
|
+
Note: ADR and NFR have been moved to the practices wing where they are
|
|
4
|
+
subclasses of method and standard respectively.
|
|
5
|
+
"""
|
|
2
6
|
|
|
3
7
|
from __future__ import annotations
|
|
4
8
|
|
|
@@ -296,116 +300,6 @@ DESIGN_SPEC: NodeDefinition = NodeDefinition(
|
|
|
296
300
|
),
|
|
297
301
|
)
|
|
298
302
|
|
|
299
|
-
ADR: NodeDefinition = NodeDefinition(
|
|
300
|
-
identity=Identity(kind="node_definition", name="adr"),
|
|
301
|
-
describes_kind="adr",
|
|
302
|
-
wing="design",
|
|
303
|
-
display_order=380,
|
|
304
|
-
directory_name="adrs",
|
|
305
|
-
is_root=True,
|
|
306
|
-
is_leaf=True,
|
|
307
|
-
is_extension=False,
|
|
308
|
-
clonable=False,
|
|
309
|
-
display_label="ADR",
|
|
310
|
-
display_label_plural="ADRs",
|
|
311
|
-
extends_kinds=(),
|
|
312
|
-
parent_rules=(),
|
|
313
|
-
fields=(
|
|
314
|
-
FieldSpec(
|
|
315
|
-
name="title",
|
|
316
|
-
field_type="string",
|
|
317
|
-
required=False,
|
|
318
|
-
description="",
|
|
319
|
-
),
|
|
320
|
-
FieldSpec(
|
|
321
|
-
name="status",
|
|
322
|
-
field_type="string",
|
|
323
|
-
required=False,
|
|
324
|
-
description="",
|
|
325
|
-
),
|
|
326
|
-
FieldSpec(
|
|
327
|
-
name="category",
|
|
328
|
-
field_type="string",
|
|
329
|
-
required=False,
|
|
330
|
-
description="",
|
|
331
|
-
),
|
|
332
|
-
FieldSpec(
|
|
333
|
-
name="scope",
|
|
334
|
-
field_type="string",
|
|
335
|
-
required=False,
|
|
336
|
-
description="Scope of the decision",
|
|
337
|
-
),
|
|
338
|
-
FieldSpec(
|
|
339
|
-
name="superseded_by",
|
|
340
|
-
field_type="string",
|
|
341
|
-
required=False,
|
|
342
|
-
description="Name of the ADR that supersedes this one",
|
|
343
|
-
),
|
|
344
|
-
),
|
|
345
|
-
cross_references=(
|
|
346
|
-
FieldRef(
|
|
347
|
-
field_name="superseded_by",
|
|
348
|
-
target_kind="adr",
|
|
349
|
-
rel_type="SUPERSEDED_BY",
|
|
350
|
-
),
|
|
351
|
-
),
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
NFR: NodeDefinition = NodeDefinition(
|
|
355
|
-
identity=Identity(kind="node_definition", name="nfr"),
|
|
356
|
-
describes_kind="nfr",
|
|
357
|
-
wing="design",
|
|
358
|
-
display_order=390,
|
|
359
|
-
directory_name="nfrs",
|
|
360
|
-
is_root=True,
|
|
361
|
-
is_leaf=True,
|
|
362
|
-
is_extension=False,
|
|
363
|
-
clonable=False,
|
|
364
|
-
display_label="NFR",
|
|
365
|
-
display_label_plural="NFRs",
|
|
366
|
-
extends_kinds=(),
|
|
367
|
-
parent_rules=(),
|
|
368
|
-
fields=(
|
|
369
|
-
FieldSpec(
|
|
370
|
-
name="title",
|
|
371
|
-
field_type="string",
|
|
372
|
-
required=False,
|
|
373
|
-
description="",
|
|
374
|
-
),
|
|
375
|
-
FieldSpec(
|
|
376
|
-
name="category",
|
|
377
|
-
field_type="string",
|
|
378
|
-
required=False,
|
|
379
|
-
description="",
|
|
380
|
-
),
|
|
381
|
-
FieldSpec(
|
|
382
|
-
name="priority",
|
|
383
|
-
field_type="string",
|
|
384
|
-
required=False,
|
|
385
|
-
description="",
|
|
386
|
-
),
|
|
387
|
-
FieldSpec(
|
|
388
|
-
name="status",
|
|
389
|
-
field_type="string",
|
|
390
|
-
required=False,
|
|
391
|
-
description="",
|
|
392
|
-
),
|
|
393
|
-
FieldSpec(
|
|
394
|
-
name="threshold",
|
|
395
|
-
field_type="string",
|
|
396
|
-
required=False,
|
|
397
|
-
description="Measurable threshold (e.g., p99 < 200ms)",
|
|
398
|
-
),
|
|
399
|
-
FieldSpec(
|
|
400
|
-
name="measurement",
|
|
401
|
-
field_type="string",
|
|
402
|
-
required=False,
|
|
403
|
-
description="How this NFR is measured",
|
|
404
|
-
),
|
|
405
|
-
),
|
|
406
|
-
cross_references=(),
|
|
407
|
-
)
|
|
408
|
-
|
|
409
303
|
SPECIFICATION: NodeDefinition = NodeDefinition(
|
|
410
304
|
identity=Identity(kind="node_definition", name="specification"),
|
|
411
305
|
describes_kind="specification",
|
|
@@ -545,8 +439,6 @@ DESIGN_WING: WingDefinition = WingDefinition(
|
|
|
545
439
|
"user_type",
|
|
546
440
|
"user_need",
|
|
547
441
|
"design_spec",
|
|
548
|
-
"adr",
|
|
549
|
-
"nfr",
|
|
550
442
|
"specification",
|
|
551
443
|
"assertion",
|
|
552
444
|
),
|
|
@@ -557,8 +449,6 @@ DESIGN_WING_NODES = [
|
|
|
557
449
|
USER_TYPE,
|
|
558
450
|
USER_NEED,
|
|
559
451
|
DESIGN_SPEC,
|
|
560
|
-
ADR,
|
|
561
|
-
NFR,
|
|
562
452
|
SPECIFICATION,
|
|
563
453
|
ASSERTION,
|
|
564
454
|
]
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""Metrics wing — metric_definition, signal_source, threshold_profile."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from katalyst_engine.core.identity import Identity
|
|
6
|
+
from katalyst_engine.schema.definition import (
|
|
7
|
+
FieldRef,
|
|
8
|
+
FieldSpec,
|
|
9
|
+
NodeDefinition,
|
|
10
|
+
WingDefinition,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
METRIC_DEFINITION: NodeDefinition = NodeDefinition(
|
|
14
|
+
identity=Identity(kind="node_definition", name="metric_definition"),
|
|
15
|
+
describes_kind="metric_definition",
|
|
16
|
+
wing="metrics",
|
|
17
|
+
display_order=700,
|
|
18
|
+
directory_name="metric_definitions",
|
|
19
|
+
is_root=True,
|
|
20
|
+
is_leaf=True,
|
|
21
|
+
is_extension=False,
|
|
22
|
+
clonable=True,
|
|
23
|
+
display_label="Metric Definition",
|
|
24
|
+
display_label_plural="Metric Definitions",
|
|
25
|
+
extends_kinds=(),
|
|
26
|
+
parent_rules=(),
|
|
27
|
+
fields=(
|
|
28
|
+
FieldSpec(
|
|
29
|
+
name="title",
|
|
30
|
+
field_type="string",
|
|
31
|
+
required=False,
|
|
32
|
+
description="",
|
|
33
|
+
),
|
|
34
|
+
FieldSpec(
|
|
35
|
+
name="description",
|
|
36
|
+
field_type="string",
|
|
37
|
+
required=False,
|
|
38
|
+
description="",
|
|
39
|
+
),
|
|
40
|
+
FieldSpec(
|
|
41
|
+
name="category",
|
|
42
|
+
field_type="string",
|
|
43
|
+
required=False,
|
|
44
|
+
description="Metric category (throughput, stability, speed, recovery)",
|
|
45
|
+
),
|
|
46
|
+
FieldSpec(
|
|
47
|
+
name="unit",
|
|
48
|
+
field_type="string",
|
|
49
|
+
required=False,
|
|
50
|
+
description="Measurement unit (deploys/day, hours, percentage)",
|
|
51
|
+
),
|
|
52
|
+
FieldSpec(
|
|
53
|
+
name="direction",
|
|
54
|
+
field_type="string",
|
|
55
|
+
required=False,
|
|
56
|
+
description="Optimization direction (higher_is_better, lower_is_better)",
|
|
57
|
+
),
|
|
58
|
+
FieldSpec(
|
|
59
|
+
name="aggregation",
|
|
60
|
+
field_type="string",
|
|
61
|
+
required=False,
|
|
62
|
+
description="Aggregation method (count_per_period, median_duration, ratio, mean_duration)",
|
|
63
|
+
),
|
|
64
|
+
FieldSpec(
|
|
65
|
+
name="inputs",
|
|
66
|
+
field_type="list",
|
|
67
|
+
required=False,
|
|
68
|
+
description="Named inputs the metric formula requires",
|
|
69
|
+
),
|
|
70
|
+
FieldSpec(
|
|
71
|
+
name="default_parameters",
|
|
72
|
+
field_type="map",
|
|
73
|
+
required=False,
|
|
74
|
+
description="Default configuration parameters for computation",
|
|
75
|
+
),
|
|
76
|
+
),
|
|
77
|
+
cross_references=(),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
SIGNAL_SOURCE: NodeDefinition = NodeDefinition(
|
|
81
|
+
identity=Identity(kind="node_definition", name="signal_source"),
|
|
82
|
+
describes_kind="signal_source",
|
|
83
|
+
wing="metrics",
|
|
84
|
+
display_order=710,
|
|
85
|
+
directory_name="signal_sources",
|
|
86
|
+
is_root=True,
|
|
87
|
+
is_leaf=True,
|
|
88
|
+
is_extension=False,
|
|
89
|
+
clonable=True,
|
|
90
|
+
display_label="Signal Source",
|
|
91
|
+
display_label_plural="Signal Sources",
|
|
92
|
+
extends_kinds=(),
|
|
93
|
+
parent_rules=(),
|
|
94
|
+
fields=(
|
|
95
|
+
FieldSpec(
|
|
96
|
+
name="title",
|
|
97
|
+
field_type="string",
|
|
98
|
+
required=False,
|
|
99
|
+
description="",
|
|
100
|
+
),
|
|
101
|
+
FieldSpec(
|
|
102
|
+
name="description",
|
|
103
|
+
field_type="string",
|
|
104
|
+
required=False,
|
|
105
|
+
description="",
|
|
106
|
+
),
|
|
107
|
+
FieldSpec(
|
|
108
|
+
name="provider",
|
|
109
|
+
field_type="string",
|
|
110
|
+
required=True,
|
|
111
|
+
description="Signal provider (github, gitlab, argocd, pagerduty, custom)",
|
|
112
|
+
),
|
|
113
|
+
FieldSpec(
|
|
114
|
+
name="signal_type",
|
|
115
|
+
field_type="string",
|
|
116
|
+
required=True,
|
|
117
|
+
description="Type of signal (deployment_event, failure_event, recovery_event, change_event)",
|
|
118
|
+
),
|
|
119
|
+
FieldSpec(
|
|
120
|
+
name="query_config",
|
|
121
|
+
field_type="map",
|
|
122
|
+
required=False,
|
|
123
|
+
description="Provider-specific query parameters",
|
|
124
|
+
),
|
|
125
|
+
FieldSpec(
|
|
126
|
+
name="field_mapping",
|
|
127
|
+
field_type="map",
|
|
128
|
+
required=False,
|
|
129
|
+
description="Maps provider fields to canonical metric input fields",
|
|
130
|
+
),
|
|
131
|
+
FieldSpec(
|
|
132
|
+
name="metric_ref",
|
|
133
|
+
field_type="string",
|
|
134
|
+
required=False,
|
|
135
|
+
description="Name of the metric_definition this source feeds",
|
|
136
|
+
),
|
|
137
|
+
),
|
|
138
|
+
cross_references=(
|
|
139
|
+
FieldRef(
|
|
140
|
+
field_name="metric_ref",
|
|
141
|
+
target_kind="metric_definition",
|
|
142
|
+
rel_type="FEEDS_METRIC",
|
|
143
|
+
),
|
|
144
|
+
),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
THRESHOLD_PROFILE: NodeDefinition = NodeDefinition(
|
|
148
|
+
identity=Identity(kind="node_definition", name="threshold_profile"),
|
|
149
|
+
describes_kind="threshold_profile",
|
|
150
|
+
wing="metrics",
|
|
151
|
+
display_order=720,
|
|
152
|
+
directory_name="threshold_profiles",
|
|
153
|
+
is_root=True,
|
|
154
|
+
is_leaf=True,
|
|
155
|
+
is_extension=False,
|
|
156
|
+
clonable=True,
|
|
157
|
+
display_label="Threshold Profile",
|
|
158
|
+
display_label_plural="Threshold Profiles",
|
|
159
|
+
extends_kinds=(),
|
|
160
|
+
parent_rules=(),
|
|
161
|
+
fields=(
|
|
162
|
+
FieldSpec(
|
|
163
|
+
name="title",
|
|
164
|
+
field_type="string",
|
|
165
|
+
required=False,
|
|
166
|
+
description="",
|
|
167
|
+
),
|
|
168
|
+
FieldSpec(
|
|
169
|
+
name="description",
|
|
170
|
+
field_type="string",
|
|
171
|
+
required=False,
|
|
172
|
+
description="",
|
|
173
|
+
),
|
|
174
|
+
FieldSpec(
|
|
175
|
+
name="scoped_to",
|
|
176
|
+
field_type="list",
|
|
177
|
+
required=False,
|
|
178
|
+
description="Systems or teams this profile applies to (empty = global default)",
|
|
179
|
+
),
|
|
180
|
+
FieldSpec(
|
|
181
|
+
name="metric_thresholds",
|
|
182
|
+
field_type="list",
|
|
183
|
+
required=False,
|
|
184
|
+
description="Per-metric band definitions with operator and value",
|
|
185
|
+
),
|
|
186
|
+
),
|
|
187
|
+
cross_references=(),
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
METRICS_WING: WingDefinition = WingDefinition(
|
|
191
|
+
identity=Identity(kind="wing_definition", name="metrics"),
|
|
192
|
+
describes_kind="metrics",
|
|
193
|
+
display_name="Metrics",
|
|
194
|
+
member_kinds=("metric_definition", "signal_source", "threshold_profile"),
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
METRICS_WING_NODES = [METRIC_DEFINITION, SIGNAL_SOURCE, THRESHOLD_PROFILE]
|