ssot-cli 0.1.5__tar.gz → 0.1.6.dev1__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.
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/PKG-INFO +23 -3
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/README.md +20 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/pyproject.toml +3 -3
- ssot_cli-0.1.6.dev1/src/ssot_cli/adr_cmd.py +166 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/boundary_cmd.py +31 -31
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/claim_cmd.py +38 -38
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/common.py +6 -2
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/evidence_cmd.py +31 -31
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/feature_cmd.py +55 -51
- ssot_cli-0.1.6.dev1/src/ssot_cli/graph_cmd.py +28 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/init_cmd.py +10 -6
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/issue_cmd.py +47 -47
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/main.py +16 -3
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/profile_cmd.py +34 -34
- ssot_cli-0.1.6.dev1/src/ssot_cli/registry_cmd.py +28 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/release_cmd.py +38 -38
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/risk_cmd.py +43 -43
- ssot_cli-0.1.6.dev1/src/ssot_cli/spec_cmd.py +192 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/test_cmd.py +30 -30
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/upgrade_cmd.py +9 -5
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/validate_cmd.py +7 -3
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli.egg-info/PKG-INFO +23 -3
- ssot_cli-0.1.6.dev1/src/ssot_cli.egg-info/requires.txt +5 -0
- ssot_cli-0.1.5/src/ssot_cli/adr_cmd.py +0 -147
- ssot_cli-0.1.5/src/ssot_cli/graph_cmd.py +0 -20
- ssot_cli-0.1.5/src/ssot_cli/registry_cmd.py +0 -20
- ssot_cli-0.1.5/src/ssot_cli/spec_cmd.py +0 -150
- ssot_cli-0.1.5/src/ssot_cli.egg-info/requires.txt +0 -5
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/setup.cfg +0 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli/__init__.py +0 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli.egg-info/SOURCES.txt +0 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli.egg-info/dependency_links.txt +0 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli.egg-info/entry_points.txt +0 -0
- {ssot_cli-0.1.5 → ssot_cli-0.1.6.dev1}/src/ssot_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ssot-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6.dev1
|
|
4
4
|
Summary: Primary CLI distribution for ssot-registry.
|
|
5
5
|
Author-email: Jacob Stewart <jacob@swarmauri.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -24,8 +24,8 @@ Classifier: Topic :: Software Development :: Quality Assurance
|
|
|
24
24
|
Classifier: Topic :: Utilities
|
|
25
25
|
Requires-Python: <3.14,>=3.10
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
|
-
Requires-Dist: ssot-contracts<0.3.0,>=0.2.
|
|
28
|
-
Requires-Dist: ssot-core<0.3.0,>=0.2.
|
|
27
|
+
Requires-Dist: ssot-contracts<0.3.0,>=0.2.11.dev1
|
|
28
|
+
Requires-Dist: ssot-core<0.3.0,>=0.2.11.dev1
|
|
29
29
|
Requires-Dist: tomli>=2.0.1; python_version < "3.11"
|
|
30
30
|
|
|
31
31
|
<div align="center">
|
|
@@ -84,6 +84,26 @@ Boundaries and releases are intentionally different:
|
|
|
84
84
|
- Freezing a boundary locks that resolved scope and emits a boundary snapshot.
|
|
85
85
|
- A release points at a frozen boundary and then bundles claims and evidence for certify, promote, publish, and revoke workflows.
|
|
86
86
|
|
|
87
|
+
## Entity intent
|
|
88
|
+
|
|
89
|
+
Operators should read the top-level entity commands this way:
|
|
90
|
+
|
|
91
|
+
- `adr`: architectural decision records that capture why the system is designed the way it is.
|
|
92
|
+
- `spec`: specification documents that define normative, operational, governance, or local-policy contract.
|
|
93
|
+
- `feature`: implementation units that connect planning, delivery status, tests, claims, and SPEC coverage.
|
|
94
|
+
- `profile`: reusable capability or deployment bundles composed from features and nested profiles.
|
|
95
|
+
- `test`: verification rows that point at executable or procedural checks.
|
|
96
|
+
- `claim`: tiered statements about system behavior that must be supported by tests and evidence.
|
|
97
|
+
- `evidence`: concrete artifacts, reports, bundles, or logs that substantiate tests and claims.
|
|
98
|
+
- `issue`: plannable defects or work items that may block a release.
|
|
99
|
+
- `risk`: tracked exposure that must be mitigated, accepted, or retired.
|
|
100
|
+
- `boundary`: scoped delivery definition used to decide what a release is evaluated against.
|
|
101
|
+
- `release`: publication unit tied to a frozen boundary plus the claims and evidence needed for certification.
|
|
102
|
+
- `graph`: relationship export view of the registry.
|
|
103
|
+
- `registry`: full-document export view of the registry.
|
|
104
|
+
|
|
105
|
+
Each command's `--help` now describes not just what it does mechanically, but why an operator would use it and what each flag is meant to control.
|
|
106
|
+
|
|
87
107
|
## CLI quick reference
|
|
88
108
|
|
|
89
109
|
```bash
|
|
@@ -54,6 +54,26 @@ Boundaries and releases are intentionally different:
|
|
|
54
54
|
- Freezing a boundary locks that resolved scope and emits a boundary snapshot.
|
|
55
55
|
- A release points at a frozen boundary and then bundles claims and evidence for certify, promote, publish, and revoke workflows.
|
|
56
56
|
|
|
57
|
+
## Entity intent
|
|
58
|
+
|
|
59
|
+
Operators should read the top-level entity commands this way:
|
|
60
|
+
|
|
61
|
+
- `adr`: architectural decision records that capture why the system is designed the way it is.
|
|
62
|
+
- `spec`: specification documents that define normative, operational, governance, or local-policy contract.
|
|
63
|
+
- `feature`: implementation units that connect planning, delivery status, tests, claims, and SPEC coverage.
|
|
64
|
+
- `profile`: reusable capability or deployment bundles composed from features and nested profiles.
|
|
65
|
+
- `test`: verification rows that point at executable or procedural checks.
|
|
66
|
+
- `claim`: tiered statements about system behavior that must be supported by tests and evidence.
|
|
67
|
+
- `evidence`: concrete artifacts, reports, bundles, or logs that substantiate tests and claims.
|
|
68
|
+
- `issue`: plannable defects or work items that may block a release.
|
|
69
|
+
- `risk`: tracked exposure that must be mitigated, accepted, or retired.
|
|
70
|
+
- `boundary`: scoped delivery definition used to decide what a release is evaluated against.
|
|
71
|
+
- `release`: publication unit tied to a frozen boundary plus the claims and evidence needed for certification.
|
|
72
|
+
- `graph`: relationship export view of the registry.
|
|
73
|
+
- `registry`: full-document export view of the registry.
|
|
74
|
+
|
|
75
|
+
Each command's `--help` now describes not just what it does mechanically, but why an operator would use it and what each flag is meant to control.
|
|
76
|
+
|
|
57
77
|
## CLI quick reference
|
|
58
78
|
|
|
59
79
|
```bash
|
|
@@ -4,15 +4,15 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ssot-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.6.dev1"
|
|
8
8
|
description = "Primary CLI distribution for ssot-registry."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10,<3.14"
|
|
11
11
|
license = "Apache-2.0"
|
|
12
12
|
authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
|
|
13
13
|
dependencies = [
|
|
14
|
-
"ssot-contracts>=0.2.
|
|
15
|
-
"ssot-core>=0.2.
|
|
14
|
+
"ssot-contracts>=0.2.11.dev1,<0.3.0",
|
|
15
|
+
"ssot-core>=0.2.11.dev1,<0.3.0",
|
|
16
16
|
"tomli>=2.0.1; python_version < '3.11'",
|
|
17
17
|
]
|
|
18
18
|
keywords = ["ssot", "cli", "registry", "governance", "release-management", "validation", "developer-tools"]
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
from ssot_registry.api import (
|
|
6
|
+
create_document,
|
|
7
|
+
create_document_reservation,
|
|
8
|
+
delete_document,
|
|
9
|
+
get_document,
|
|
10
|
+
list_document_reservations,
|
|
11
|
+
list_documents,
|
|
12
|
+
set_document_status,
|
|
13
|
+
sync_documents,
|
|
14
|
+
supersede_documents,
|
|
15
|
+
update_document,
|
|
16
|
+
)
|
|
17
|
+
from ssot_cli.common import add_path_argument, compact_dict
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_adr(subparsers: argparse._SubParsersAction) -> None:
|
|
21
|
+
adr = subparsers.add_parser(
|
|
22
|
+
"adr",
|
|
23
|
+
help="ADR operations.",
|
|
24
|
+
description="Architectural decision records capture why the system is designed the way it is and preserve decision history.",
|
|
25
|
+
)
|
|
26
|
+
adr_sub = adr.add_subparsers(dest="adr_command", required=True)
|
|
27
|
+
|
|
28
|
+
create = adr_sub.add_parser(
|
|
29
|
+
"create",
|
|
30
|
+
help="Author a new architectural decision record.",
|
|
31
|
+
description="Create an ADR that captures a design decision, its rationale, and its document source.",
|
|
32
|
+
)
|
|
33
|
+
add_path_argument(create)
|
|
34
|
+
create.add_argument("--title", required=True, help="Human-readable ADR title shown to operators and reviewers.")
|
|
35
|
+
create.add_argument("--slug", required=True, help="Stable slug used to derive the ADR document id and filename.")
|
|
36
|
+
create.add_argument("--body", default=None, help="Inline ADR body text to persist without a separate authored payload file.")
|
|
37
|
+
create.add_argument("--body-file", default=None, help="Path to the ADR YAML or JSON body payload to import into the registry.")
|
|
38
|
+
create.add_argument("--number", type=int, default=None, help="Explicit ADR number to assign instead of auto-allocation.")
|
|
39
|
+
create.add_argument("--status", choices=["draft", "in_review", "accepted", "rejected", "withdrawn", "superseded", "retired"], default="draft", help="Current decision lifecycle state for the ADR.")
|
|
40
|
+
create.add_argument("--note", default=None, help="Lifecycle note that explains review, acceptance, or retirement context.")
|
|
41
|
+
create.add_argument("--origin", choices=["repo-local", "ssot-origin", "ssot-core"], default="repo-local", help="Source authority for the ADR document.")
|
|
42
|
+
create.add_argument("--reserve-range", default=None, help="Named reservation range to allocate the ADR number from.")
|
|
43
|
+
create.set_defaults(func=run_create)
|
|
44
|
+
|
|
45
|
+
get = adr_sub.add_parser("get", help="Show one ADR.", description="Fetch a single ADR by id for review or automation.")
|
|
46
|
+
add_path_argument(get)
|
|
47
|
+
get.add_argument("--id", required=True, help="ADR id to retrieve.")
|
|
48
|
+
get.set_defaults(func=run_get)
|
|
49
|
+
|
|
50
|
+
list_cmd = adr_sub.add_parser("list", help="List ADRs.", description="List ADR documents currently known to the registry.")
|
|
51
|
+
add_path_argument(list_cmd)
|
|
52
|
+
list_cmd.set_defaults(func=run_list)
|
|
53
|
+
|
|
54
|
+
update = adr_sub.add_parser(
|
|
55
|
+
"update",
|
|
56
|
+
help="Edit a repo-local ADR.",
|
|
57
|
+
description="Update mutable ADR fields such as title, body source, status, or lifecycle note.",
|
|
58
|
+
)
|
|
59
|
+
add_path_argument(update)
|
|
60
|
+
update.add_argument("--id", required=True, help="ADR id to update.")
|
|
61
|
+
update.add_argument("--title", default=None, help="Replacement ADR title.")
|
|
62
|
+
update.add_argument("--body", default=None, help="Replacement inline ADR body text.")
|
|
63
|
+
update.add_argument("--body-file", default=None, help="Replacement ADR body file to ingest.")
|
|
64
|
+
update.add_argument("--status", choices=["draft", "in_review", "accepted", "rejected", "withdrawn", "superseded", "retired"], default=None, help="New lifecycle state for the ADR.")
|
|
65
|
+
update.add_argument("--note", default=None, help="Updated lifecycle note or rationale.")
|
|
66
|
+
update.set_defaults(func=run_update)
|
|
67
|
+
|
|
68
|
+
set_status = adr_sub.add_parser(
|
|
69
|
+
"set-status",
|
|
70
|
+
help="Advance or revise ADR status.",
|
|
71
|
+
description="Change the lifecycle state of an ADR without editing other document fields.",
|
|
72
|
+
)
|
|
73
|
+
add_path_argument(set_status)
|
|
74
|
+
set_status.add_argument("--id", required=True, help="ADR id whose status should change.")
|
|
75
|
+
set_status.add_argument("--status", required=True, choices=["draft", "in_review", "accepted", "rejected", "withdrawn", "superseded", "retired"], help="Target lifecycle state to set.")
|
|
76
|
+
set_status.add_argument("--note", default=None, help="Reason or context for the status transition.")
|
|
77
|
+
set_status.set_defaults(func=run_set_status)
|
|
78
|
+
|
|
79
|
+
supersede = adr_sub.add_parser(
|
|
80
|
+
"supersede",
|
|
81
|
+
help="Mark older ADRs as replaced.",
|
|
82
|
+
description="Record that one ADR supersedes one or more earlier ADRs.",
|
|
83
|
+
)
|
|
84
|
+
add_path_argument(supersede)
|
|
85
|
+
supersede.add_argument("--id", required=True, help="Newer ADR that supersedes prior decisions.")
|
|
86
|
+
supersede.add_argument("--supersedes", nargs="+", required=True, help="ADR ids that are being replaced by `--id`.")
|
|
87
|
+
supersede.add_argument("--note", default=None, help="Transition note explaining why the older ADRs were superseded.")
|
|
88
|
+
supersede.set_defaults(func=run_supersede)
|
|
89
|
+
|
|
90
|
+
delete = adr_sub.add_parser("delete", help="Delete a repo-local ADR.", description="Remove a repo-local ADR entry and its associated document metadata.")
|
|
91
|
+
add_path_argument(delete)
|
|
92
|
+
delete.add_argument("--id", required=True, help="ADR id to delete.")
|
|
93
|
+
delete.set_defaults(func=run_delete)
|
|
94
|
+
|
|
95
|
+
sync = adr_sub.add_parser("sync", help="Refresh packaged ADRs.", description="Sync packaged ADR documents from installed sources into the repository.")
|
|
96
|
+
add_path_argument(sync)
|
|
97
|
+
sync.set_defaults(func=run_sync)
|
|
98
|
+
|
|
99
|
+
reserve = adr_sub.add_parser("reserve", help="Manage ADR number ranges.", description="Reserve ADR number ranges for a team, owner, or local namespace.")
|
|
100
|
+
reserve_sub = reserve.add_subparsers(dest="adr_reserve_command", required=True)
|
|
101
|
+
reserve_create = reserve_sub.add_parser("create", help="Reserve ADR numbers.", description="Create a repo-local reservation range for ADR numbering.")
|
|
102
|
+
add_path_argument(reserve_create)
|
|
103
|
+
reserve_create.add_argument("--name", required=True, help="Reservation owner or label.")
|
|
104
|
+
reserve_create.add_argument("--start", type=int, required=True, help="First ADR number included in the reservation.")
|
|
105
|
+
reserve_create.add_argument("--end", type=int, required=True, help="Last ADR number included in the reservation.")
|
|
106
|
+
reserve_create.set_defaults(func=run_reserve_create)
|
|
107
|
+
|
|
108
|
+
reserve_list = reserve_sub.add_parser("list", help="List ADR reservations.", description="Show ADR numbering reservations currently defined in the repository.")
|
|
109
|
+
add_path_argument(reserve_list)
|
|
110
|
+
reserve_list.set_defaults(func=run_reserve_list)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def run_create(args: argparse.Namespace) -> dict[str, object]:
|
|
114
|
+
return create_document(
|
|
115
|
+
args.path,
|
|
116
|
+
"adr",
|
|
117
|
+
title=args.title,
|
|
118
|
+
slug=args.slug,
|
|
119
|
+
body=args.body,
|
|
120
|
+
body_file=args.body_file,
|
|
121
|
+
number=args.number,
|
|
122
|
+
origin=args.origin,
|
|
123
|
+
reserve_range=args.reserve_range,
|
|
124
|
+
status=args.status,
|
|
125
|
+
note=args.note,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def run_get(args: argparse.Namespace) -> dict[str, object]:
|
|
130
|
+
return get_document(args.path, "adr", args.id)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def run_list(args: argparse.Namespace) -> dict[str, object]:
|
|
134
|
+
return list_documents(args.path, "adr")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def run_update(args: argparse.Namespace) -> dict[str, object]:
|
|
138
|
+
changes = compact_dict({"title": args.title, "body": args.body, "body_file": args.body_file, "status": args.status, "note": args.note})
|
|
139
|
+
if not changes:
|
|
140
|
+
raise ValueError("At least one update field is required")
|
|
141
|
+
return update_document(args.path, "adr", args.id, **changes)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def run_set_status(args: argparse.Namespace) -> dict[str, object]:
|
|
145
|
+
return set_document_status(args.path, "adr", args.id, status=args.status, note=args.note)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def run_supersede(args: argparse.Namespace) -> dict[str, object]:
|
|
149
|
+
return supersede_documents(args.path, "adr", args.id, supersedes=args.supersedes, note=args.note)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def run_delete(args: argparse.Namespace) -> dict[str, object]:
|
|
153
|
+
return delete_document(args.path, "adr", args.id)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def run_sync(args: argparse.Namespace) -> dict[str, object]:
|
|
157
|
+
return sync_documents(args.path, "adr")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def run_reserve_create(args: argparse.Namespace) -> dict[str, object]:
|
|
161
|
+
return create_document_reservation(args.path, "adr", name=args.name, start=args.start, end=args.end)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def run_reserve_list(args: argparse.Namespace) -> dict[str, object]:
|
|
165
|
+
return list_document_reservations(args.path, "adr")
|
|
166
|
+
|
|
@@ -25,65 +25,65 @@ def register_boundary(subparsers: argparse._SubParsersAction) -> None:
|
|
|
25
25
|
)
|
|
26
26
|
boundary_sub = boundary.add_subparsers(dest="boundary_command", required=True)
|
|
27
27
|
|
|
28
|
-
create = boundary_sub.add_parser("create", help="Create a boundary.")
|
|
28
|
+
create = boundary_sub.add_parser("create", help="Define a release boundary.", description="Create a scoped delivery boundary that selects the features and profiles a release is evaluated against.")
|
|
29
29
|
add_path_argument(create)
|
|
30
|
-
create.add_argument("--id", required=True)
|
|
31
|
-
create.add_argument("--title", required=True)
|
|
32
|
-
create.add_argument("--status", choices=["draft", "active", "frozen", "retired"], default="draft")
|
|
33
|
-
add_optional_bool_argument(create, "--frozen", default=False, help_text="
|
|
34
|
-
create.add_argument("--feature-ids", nargs="*", default=[])
|
|
35
|
-
create.add_argument("--profile-ids", nargs="*", default=[])
|
|
30
|
+
create.add_argument("--id", required=True, help="Normalized boundary id to create.")
|
|
31
|
+
create.add_argument("--title", required=True, help="Human-readable boundary title.")
|
|
32
|
+
create.add_argument("--status", choices=["draft", "active", "frozen", "retired"], default="draft", help="Current lifecycle state of the boundary.")
|
|
33
|
+
add_optional_bool_argument(create, "--frozen", default=False, help_text="Record whether the boundary contents are locked against further scope edits.")
|
|
34
|
+
create.add_argument("--feature-ids", nargs="*", default=[], help="Direct feature ids included in the scoped delivery unit.")
|
|
35
|
+
create.add_argument("--profile-ids", nargs="*", default=[], help="Profile ids included in the scoped delivery unit.")
|
|
36
36
|
create.set_defaults(func=run_create)
|
|
37
37
|
|
|
38
|
-
get = boundary_sub.add_parser("get", help="
|
|
38
|
+
get = boundary_sub.add_parser("get", help="Show one boundary.", description="Fetch a single boundary by id.")
|
|
39
39
|
add_path_argument(get)
|
|
40
|
-
get.add_argument("--id", required=True)
|
|
40
|
+
get.add_argument("--id", required=True, help="Boundary id to retrieve.")
|
|
41
41
|
get.set_defaults(func=run_get)
|
|
42
42
|
|
|
43
|
-
list_cmd = boundary_sub.add_parser("list", help="List boundaries.")
|
|
43
|
+
list_cmd = boundary_sub.add_parser("list", help="List boundaries.", description="List boundary records currently known to the registry.")
|
|
44
44
|
add_path_argument(list_cmd)
|
|
45
45
|
list_cmd.set_defaults(func=run_list)
|
|
46
46
|
|
|
47
|
-
update = boundary_sub.add_parser("update", help="Update boundary fields.")
|
|
47
|
+
update = boundary_sub.add_parser("update", help="Edit boundary metadata.", description="Update mutable boundary fields without changing the feature or profile membership lists.")
|
|
48
48
|
add_path_argument(update)
|
|
49
|
-
update.add_argument("--id", required=True)
|
|
50
|
-
update.add_argument("--title", default=None)
|
|
51
|
-
update.add_argument("--status", choices=["draft", "active", "frozen", "retired"], default=None)
|
|
52
|
-
add_optional_bool_argument(update, "--frozen", default=None, help_text="
|
|
49
|
+
update.add_argument("--id", required=True, help="Boundary id to update.")
|
|
50
|
+
update.add_argument("--title", default=None, help="Replacement boundary title.")
|
|
51
|
+
update.add_argument("--status", choices=["draft", "active", "frozen", "retired"], default=None, help="Updated lifecycle state.")
|
|
52
|
+
add_optional_bool_argument(update, "--frozen", default=None, help_text="Change whether the boundary is locked against scope edits.")
|
|
53
53
|
update.set_defaults(func=run_update)
|
|
54
54
|
|
|
55
|
-
delete = boundary_sub.add_parser("delete", help="Delete a boundary.")
|
|
55
|
+
delete = boundary_sub.add_parser("delete", help="Delete a boundary.", description="Remove a boundary record from the registry.")
|
|
56
56
|
add_path_argument(delete)
|
|
57
|
-
delete.add_argument("--id", required=True)
|
|
57
|
+
delete.add_argument("--id", required=True, help="Boundary id to delete.")
|
|
58
58
|
delete.set_defaults(func=run_delete)
|
|
59
59
|
|
|
60
|
-
add_feature = boundary_sub.add_parser("add-feature", help="Add
|
|
60
|
+
add_feature = boundary_sub.add_parser("add-feature", help="Add features to a boundary.", description="Include one or more direct features in the scoped delivery boundary.")
|
|
61
61
|
add_path_argument(add_feature)
|
|
62
|
-
add_feature.add_argument("--id", required=True)
|
|
63
|
-
add_feature.add_argument("--feature-ids", nargs="+", required=True)
|
|
62
|
+
add_feature.add_argument("--id", required=True, help="Boundary id that should receive the features.")
|
|
63
|
+
add_feature.add_argument("--feature-ids", nargs="+", required=True, help="Feature ids to include in the boundary.")
|
|
64
64
|
add_feature.set_defaults(func=run_add_feature)
|
|
65
65
|
|
|
66
|
-
remove_feature = boundary_sub.add_parser("remove-feature", help="Remove
|
|
66
|
+
remove_feature = boundary_sub.add_parser("remove-feature", help="Remove features from a boundary.", description="Remove one or more direct features from the scoped delivery boundary.")
|
|
67
67
|
add_path_argument(remove_feature)
|
|
68
|
-
remove_feature.add_argument("--id", required=True)
|
|
69
|
-
remove_feature.add_argument("--feature-ids", nargs="+", required=True)
|
|
68
|
+
remove_feature.add_argument("--id", required=True, help="Boundary id whose features should be removed.")
|
|
69
|
+
remove_feature.add_argument("--feature-ids", nargs="+", required=True, help="Feature ids to remove from the boundary.")
|
|
70
70
|
remove_feature.set_defaults(func=run_remove_feature)
|
|
71
71
|
|
|
72
|
-
add_profile = boundary_sub.add_parser("add-profile", help="Add
|
|
72
|
+
add_profile = boundary_sub.add_parser("add-profile", help="Add profiles to a boundary.", description="Include one or more profiles in the scoped delivery boundary.")
|
|
73
73
|
add_path_argument(add_profile)
|
|
74
|
-
add_profile.add_argument("--id", required=True)
|
|
75
|
-
add_profile.add_argument("--profile-ids", nargs="+", required=True)
|
|
74
|
+
add_profile.add_argument("--id", required=True, help="Boundary id that should receive the profiles.")
|
|
75
|
+
add_profile.add_argument("--profile-ids", nargs="+", required=True, help="Profile ids to include in the boundary.")
|
|
76
76
|
add_profile.set_defaults(func=run_add_profile)
|
|
77
77
|
|
|
78
|
-
remove_profile = boundary_sub.add_parser("remove-profile", help="Remove
|
|
78
|
+
remove_profile = boundary_sub.add_parser("remove-profile", help="Remove profiles from a boundary.", description="Remove one or more profiles from the scoped delivery boundary.")
|
|
79
79
|
add_path_argument(remove_profile)
|
|
80
|
-
remove_profile.add_argument("--id", required=True)
|
|
81
|
-
remove_profile.add_argument("--profile-ids", nargs="+", required=True)
|
|
80
|
+
remove_profile.add_argument("--id", required=True, help="Boundary id whose profiles should be removed.")
|
|
81
|
+
remove_profile.add_argument("--profile-ids", nargs="+", required=True, help="Profile ids to remove from the boundary.")
|
|
82
82
|
remove_profile.set_defaults(func=run_remove_profile)
|
|
83
83
|
|
|
84
|
-
freeze = boundary_sub.add_parser("freeze", help="Freeze a boundary and emit a snapshot.")
|
|
84
|
+
freeze = boundary_sub.add_parser("freeze", help="Freeze boundary scope.", description="Lock a boundary's resolved scope and emit a snapshot suitable for release workflows.")
|
|
85
85
|
add_path_argument(freeze)
|
|
86
|
-
freeze.add_argument("--boundary-id", default=None, help="Boundary id.
|
|
86
|
+
freeze.add_argument("--boundary-id", default=None, help="Boundary id to freeze. Omit to freeze the active boundary.")
|
|
87
87
|
freeze.set_defaults(func=run_freeze)
|
|
88
88
|
|
|
89
89
|
|
|
@@ -32,72 +32,72 @@ def register_claim(subparsers: argparse._SubParsersAction) -> None:
|
|
|
32
32
|
)
|
|
33
33
|
claim_sub = claim.add_subparsers(dest="claim_command", required=True)
|
|
34
34
|
|
|
35
|
-
create = claim_sub.add_parser("create", help="Create a claim.")
|
|
35
|
+
create = claim_sub.add_parser("create", help="Register a new assurance claim.", description="Create a tiered claim about system behavior and link it to supporting features, tests, and evidence.")
|
|
36
36
|
add_path_argument(create)
|
|
37
|
-
create.add_argument("--id", required=True)
|
|
38
|
-
create.add_argument("--title", required=True)
|
|
39
|
-
create.add_argument("--status", choices=["proposed", "declared", "implemented", "asserted", "evidenced", "certified", "promoted", "published", "blocked", "retired"], default="proposed")
|
|
40
|
-
create.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default="T0")
|
|
41
|
-
create.add_argument("--kind", required=True)
|
|
42
|
-
create.add_argument("--description", default="")
|
|
43
|
-
create.add_argument("--feature-ids", nargs="*", default=[])
|
|
44
|
-
create.add_argument("--test-ids", nargs="*", default=[])
|
|
45
|
-
create.add_argument("--evidence-ids", nargs="*", default=[])
|
|
37
|
+
create.add_argument("--id", required=True, help="Normalized claim id to create.")
|
|
38
|
+
create.add_argument("--title", required=True, help="Human-readable claim title.")
|
|
39
|
+
create.add_argument("--status", choices=["proposed", "declared", "implemented", "asserted", "evidenced", "certified", "promoted", "published", "blocked", "retired"], default="proposed", help="Current maturity or publication state of the claim.")
|
|
40
|
+
create.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default="T0", help="Assurance tier required for the claim.")
|
|
41
|
+
create.add_argument("--kind", required=True, help="Operator-defined claim category.")
|
|
42
|
+
create.add_argument("--description", default="", help="What the claim asserts and why it matters.")
|
|
43
|
+
create.add_argument("--feature-ids", nargs="*", default=[], help="Feature ids the claim is about.")
|
|
44
|
+
create.add_argument("--test-ids", nargs="*", default=[], help="Test ids that support the claim.")
|
|
45
|
+
create.add_argument("--evidence-ids", nargs="*", default=[], help="Evidence ids that substantiate the claim.")
|
|
46
46
|
create.set_defaults(func=run_create)
|
|
47
47
|
|
|
48
|
-
get = claim_sub.add_parser("get", help="
|
|
48
|
+
get = claim_sub.add_parser("get", help="Show one claim.", description="Fetch a single claim record by id.")
|
|
49
49
|
add_path_argument(get)
|
|
50
|
-
get.add_argument("--id", required=True)
|
|
50
|
+
get.add_argument("--id", required=True, help="Claim id to retrieve.")
|
|
51
51
|
get.set_defaults(func=run_get)
|
|
52
52
|
|
|
53
|
-
list_cmd = claim_sub.add_parser("list", help="List claims.")
|
|
53
|
+
list_cmd = claim_sub.add_parser("list", help="List claims.", description="List claim records currently known to the registry.")
|
|
54
54
|
add_path_argument(list_cmd)
|
|
55
55
|
list_cmd.set_defaults(func=run_list)
|
|
56
56
|
|
|
57
|
-
update = claim_sub.add_parser("update", help="Update claim fields.")
|
|
57
|
+
update = claim_sub.add_parser("update", help="Edit claim metadata.", description="Update mutable claim fields without changing its linked support graph.")
|
|
58
58
|
add_path_argument(update)
|
|
59
|
-
update.add_argument("--id", required=True)
|
|
60
|
-
update.add_argument("--title", default=None)
|
|
61
|
-
update.add_argument("--kind", default=None)
|
|
62
|
-
update.add_argument("--description", default=None)
|
|
59
|
+
update.add_argument("--id", required=True, help="Claim id to update.")
|
|
60
|
+
update.add_argument("--title", default=None, help="Replacement claim title.")
|
|
61
|
+
update.add_argument("--kind", default=None, help="Updated claim category.")
|
|
62
|
+
update.add_argument("--description", default=None, help="Replacement claim description.")
|
|
63
63
|
update.set_defaults(func=run_update)
|
|
64
64
|
|
|
65
|
-
delete = claim_sub.add_parser("delete", help="Delete a claim.")
|
|
65
|
+
delete = claim_sub.add_parser("delete", help="Delete a claim.", description="Remove a claim record from the registry.")
|
|
66
66
|
add_path_argument(delete)
|
|
67
|
-
delete.add_argument("--id", required=True)
|
|
67
|
+
delete.add_argument("--id", required=True, help="Claim id to delete.")
|
|
68
68
|
delete.set_defaults(func=run_delete)
|
|
69
69
|
|
|
70
|
-
link = claim_sub.add_parser("link", help="
|
|
70
|
+
link = claim_sub.add_parser("link", help="Attach related records to a claim.", description="Add links from a claim to the features, tests, or evidence that support it.")
|
|
71
71
|
add_path_argument(link)
|
|
72
|
-
link.add_argument("--id", required=True)
|
|
73
|
-
link.add_argument("--feature-ids", nargs="*")
|
|
74
|
-
link.add_argument("--test-ids", nargs="*")
|
|
75
|
-
link.add_argument("--evidence-ids", nargs="*")
|
|
72
|
+
link.add_argument("--id", required=True, help="Claim id that should receive the links.")
|
|
73
|
+
link.add_argument("--feature-ids", nargs="*", help="Feature ids to attach.")
|
|
74
|
+
link.add_argument("--test-ids", nargs="*", help="Test ids to attach.")
|
|
75
|
+
link.add_argument("--evidence-ids", nargs="*", help="Evidence ids to attach.")
|
|
76
76
|
link.set_defaults(func=run_link)
|
|
77
77
|
|
|
78
|
-
unlink = claim_sub.add_parser("unlink", help="
|
|
78
|
+
unlink = claim_sub.add_parser("unlink", help="Remove related records from a claim.", description="Remove links from a claim to features, tests, or evidence.")
|
|
79
79
|
add_path_argument(unlink)
|
|
80
|
-
unlink.add_argument("--id", required=True)
|
|
81
|
-
unlink.add_argument("--feature-ids", nargs="*")
|
|
82
|
-
unlink.add_argument("--test-ids", nargs="*")
|
|
83
|
-
unlink.add_argument("--evidence-ids", nargs="*")
|
|
80
|
+
unlink.add_argument("--id", required=True, help="Claim id whose links should be removed.")
|
|
81
|
+
unlink.add_argument("--feature-ids", nargs="*", help="Feature ids to detach.")
|
|
82
|
+
unlink.add_argument("--test-ids", nargs="*", help="Test ids to detach.")
|
|
83
|
+
unlink.add_argument("--evidence-ids", nargs="*", help="Evidence ids to detach.")
|
|
84
84
|
unlink.set_defaults(func=run_unlink)
|
|
85
85
|
|
|
86
|
-
evaluate = claim_sub.add_parser("evaluate", help="Evaluate one claim or
|
|
86
|
+
evaluate = claim_sub.add_parser("evaluate", help="Evaluate claim support.", description="Recompute claim support and readiness for one claim or the entire registry.")
|
|
87
87
|
add_path_argument(evaluate)
|
|
88
|
-
evaluate.add_argument("--claim-id", default=None, help="Claim id to evaluate. Omit to evaluate
|
|
88
|
+
evaluate.add_argument("--claim-id", default=None, help="Claim id to evaluate. Omit to evaluate every claim in the registry.")
|
|
89
89
|
evaluate.set_defaults(func=run_evaluate)
|
|
90
90
|
|
|
91
|
-
set_status = claim_sub.add_parser("set-status", help="
|
|
91
|
+
set_status = claim_sub.add_parser("set-status", help="Advance or revise claim status.", description="Change the lifecycle status of a claim without editing other fields.")
|
|
92
92
|
add_path_argument(set_status)
|
|
93
|
-
set_status.add_argument("--id", required=True)
|
|
94
|
-
set_status.add_argument("--status", required=True, choices=["proposed", "declared", "implemented", "asserted", "evidenced", "certified", "promoted", "published", "blocked", "retired"])
|
|
93
|
+
set_status.add_argument("--id", required=True, help="Claim id whose status should change.")
|
|
94
|
+
set_status.add_argument("--status", required=True, choices=["proposed", "declared", "implemented", "asserted", "evidenced", "certified", "promoted", "published", "blocked", "retired"], help="Target lifecycle or publication state.")
|
|
95
95
|
set_status.set_defaults(func=run_set_status)
|
|
96
96
|
|
|
97
|
-
set_tier = claim_sub.add_parser("set-tier", help="
|
|
97
|
+
set_tier = claim_sub.add_parser("set-tier", help="Change claim tier.", description="Set the assurance tier expected for a claim.")
|
|
98
98
|
add_path_argument(set_tier)
|
|
99
|
-
set_tier.add_argument("--id", required=True)
|
|
100
|
-
set_tier.add_argument("--tier", required=True, choices=["T0", "T1", "T2", "T3", "T4"])
|
|
99
|
+
set_tier.add_argument("--id", required=True, help="Claim id whose tier should change.")
|
|
100
|
+
set_tier.add_argument("--tier", required=True, choices=["T0", "T1", "T2", "T3", "T4"], help="Target assurance tier to assign.")
|
|
101
101
|
set_tier.set_defaults(func=run_set_tier)
|
|
102
102
|
|
|
103
103
|
|
|
@@ -5,7 +5,12 @@ from typing import Any
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def add_path_argument(parser: argparse.ArgumentParser) -> None:
|
|
8
|
-
parser.add_argument(
|
|
8
|
+
parser.add_argument(
|
|
9
|
+
"path",
|
|
10
|
+
nargs="?",
|
|
11
|
+
default=".",
|
|
12
|
+
help="Repository root or registry file to operate on. Defaults to the current directory.",
|
|
13
|
+
)
|
|
9
14
|
|
|
10
15
|
|
|
11
16
|
def add_id_argument(parser: argparse.ArgumentParser, flag: str = "--id", *, dest: str | None = None, help_text: str = "Normalized id.") -> None:
|
|
@@ -34,4 +39,3 @@ def collect_list_fields(args: argparse.Namespace, mapping: dict[str, str]) -> di
|
|
|
34
39
|
if value:
|
|
35
40
|
links[field_name] = value
|
|
36
41
|
return links
|
|
37
|
-
|
|
@@ -29,59 +29,59 @@ def register_evidence(subparsers: argparse._SubParsersAction) -> None:
|
|
|
29
29
|
)
|
|
30
30
|
evidence_sub = evidence.add_subparsers(dest="evidence_command", required=True)
|
|
31
31
|
|
|
32
|
-
create = evidence_sub.add_parser("create", help="Create an evidence row.")
|
|
32
|
+
create = evidence_sub.add_parser("create", help="Register a new evidence artifact.", description="Create an evidence row that points at a concrete artifact supporting tests or claims.")
|
|
33
33
|
add_path_argument(create)
|
|
34
|
-
create.add_argument("--id", required=True)
|
|
35
|
-
create.add_argument("--title", required=True)
|
|
36
|
-
create.add_argument("--status", choices=["planned", "collected", "passed", "failed", "stale"], default="planned")
|
|
37
|
-
create.add_argument("--kind", required=True)
|
|
38
|
-
create.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default="T0")
|
|
39
|
-
create.add_argument("--evidence-path", dest="evidence_path", required=True, help="Repository-relative evidence
|
|
40
|
-
create.add_argument("--claim-ids", nargs="*", default=[])
|
|
41
|
-
create.add_argument("--test-ids", nargs="*", default=[])
|
|
34
|
+
create.add_argument("--id", required=True, help="Normalized evidence id to create.")
|
|
35
|
+
create.add_argument("--title", required=True, help="Human-readable evidence title.")
|
|
36
|
+
create.add_argument("--status", choices=["planned", "collected", "passed", "failed", "stale"], default="planned", help="Current freshness or outcome state of the evidence artifact.")
|
|
37
|
+
create.add_argument("--kind", required=True, help="Operator-defined evidence category such as report, bundle, or log.")
|
|
38
|
+
create.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default="T0", help="Assurance tier the evidence contributes toward.")
|
|
39
|
+
create.add_argument("--evidence-path", dest="evidence_path", required=True, help="Repository-relative location of the evidence artifact.")
|
|
40
|
+
create.add_argument("--claim-ids", nargs="*", default=[], help="Claim ids supported by the evidence.")
|
|
41
|
+
create.add_argument("--test-ids", nargs="*", default=[], help="Test ids associated with the evidence.")
|
|
42
42
|
create.set_defaults(func=run_create)
|
|
43
43
|
|
|
44
|
-
get = evidence_sub.add_parser("get", help="
|
|
44
|
+
get = evidence_sub.add_parser("get", help="Show one evidence row.", description="Fetch a single evidence record by id.")
|
|
45
45
|
add_path_argument(get)
|
|
46
|
-
get.add_argument("--id", required=True)
|
|
46
|
+
get.add_argument("--id", required=True, help="Evidence id to retrieve.")
|
|
47
47
|
get.set_defaults(func=run_get)
|
|
48
48
|
|
|
49
|
-
list_cmd = evidence_sub.add_parser("list", help="List evidence rows.")
|
|
49
|
+
list_cmd = evidence_sub.add_parser("list", help="List evidence rows.", description="List evidence artifacts currently known to the registry.")
|
|
50
50
|
add_path_argument(list_cmd)
|
|
51
51
|
list_cmd.set_defaults(func=run_list)
|
|
52
52
|
|
|
53
|
-
update = evidence_sub.add_parser("update", help="Update evidence fields.")
|
|
53
|
+
update = evidence_sub.add_parser("update", help="Edit evidence metadata.", description="Update mutable evidence fields without changing its link graph.")
|
|
54
54
|
add_path_argument(update)
|
|
55
|
-
update.add_argument("--id", required=True)
|
|
56
|
-
update.add_argument("--title", default=None)
|
|
57
|
-
update.add_argument("--status", choices=["planned", "collected", "passed", "failed", "stale"], default=None)
|
|
58
|
-
update.add_argument("--kind", default=None)
|
|
59
|
-
update.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default=None)
|
|
60
|
-
update.add_argument("--evidence-path", dest="evidence_path", default=None)
|
|
55
|
+
update.add_argument("--id", required=True, help="Evidence id to update.")
|
|
56
|
+
update.add_argument("--title", default=None, help="Replacement evidence title.")
|
|
57
|
+
update.add_argument("--status", choices=["planned", "collected", "passed", "failed", "stale"], default=None, help="Updated freshness or outcome state.")
|
|
58
|
+
update.add_argument("--kind", default=None, help="Updated evidence category.")
|
|
59
|
+
update.add_argument("--tier", choices=["T0", "T1", "T2", "T3", "T4"], default=None, help="Updated assurance tier contribution.")
|
|
60
|
+
update.add_argument("--evidence-path", dest="evidence_path", default=None, help="Updated repository-relative path to the artifact.")
|
|
61
61
|
update.set_defaults(func=run_update)
|
|
62
62
|
|
|
63
|
-
delete = evidence_sub.add_parser("delete", help="Delete an evidence row.")
|
|
63
|
+
delete = evidence_sub.add_parser("delete", help="Delete an evidence row.", description="Remove an evidence record from the registry.")
|
|
64
64
|
add_path_argument(delete)
|
|
65
|
-
delete.add_argument("--id", required=True)
|
|
65
|
+
delete.add_argument("--id", required=True, help="Evidence id to delete.")
|
|
66
66
|
delete.set_defaults(func=run_delete)
|
|
67
67
|
|
|
68
|
-
link = evidence_sub.add_parser("link", help="
|
|
68
|
+
link = evidence_sub.add_parser("link", help="Attach related claims or tests.", description="Add links from an evidence row to the claims or tests it supports.")
|
|
69
69
|
add_path_argument(link)
|
|
70
|
-
link.add_argument("--id", required=True)
|
|
71
|
-
link.add_argument("--claim-ids", nargs="*")
|
|
72
|
-
link.add_argument("--test-ids", nargs="*")
|
|
70
|
+
link.add_argument("--id", required=True, help="Evidence id that should receive the links.")
|
|
71
|
+
link.add_argument("--claim-ids", nargs="*", help="Claim ids to attach.")
|
|
72
|
+
link.add_argument("--test-ids", nargs="*", help="Test ids to attach.")
|
|
73
73
|
link.set_defaults(func=run_link)
|
|
74
74
|
|
|
75
|
-
unlink = evidence_sub.add_parser("unlink", help="
|
|
75
|
+
unlink = evidence_sub.add_parser("unlink", help="Remove related claims or tests.", description="Remove links from an evidence row to claims or tests.")
|
|
76
76
|
add_path_argument(unlink)
|
|
77
|
-
unlink.add_argument("--id", required=True)
|
|
78
|
-
unlink.add_argument("--claim-ids", nargs="*")
|
|
79
|
-
unlink.add_argument("--test-ids", nargs="*")
|
|
77
|
+
unlink.add_argument("--id", required=True, help="Evidence id whose links should be removed.")
|
|
78
|
+
unlink.add_argument("--claim-ids", nargs="*", help="Claim ids to detach.")
|
|
79
|
+
unlink.add_argument("--test-ids", nargs="*", help="Test ids to detach.")
|
|
80
80
|
unlink.set_defaults(func=run_unlink)
|
|
81
81
|
|
|
82
|
-
verify = evidence_sub.add_parser("verify", help="Verify one evidence row or all evidence rows.")
|
|
82
|
+
verify = evidence_sub.add_parser("verify", help="Verify evidence artifacts.", description="Check one evidence row or all evidence rows for existence and readiness.")
|
|
83
83
|
add_path_argument(verify)
|
|
84
|
-
verify.add_argument("--evidence-id", default=None, help="Evidence id to verify. Omit to verify
|
|
84
|
+
verify.add_argument("--evidence-id", default=None, help="Evidence id to verify. Omit to verify every evidence row in the registry.")
|
|
85
85
|
verify.set_defaults(func=run_verify)
|
|
86
86
|
|
|
87
87
|
|